gpt4 book ai didi

c# - BackgroundWorker 是保持 WCF/WPF 应用程序响应的唯一方法吗?

转载 作者:太空狗 更新时间:2023-10-29 20:53:26 24 4
gpt4 key购买 nike

使用 C#、WCF、WPF 的客户端/服务器桌面应用程序。由于几乎每个操作都需要访问服务器(列出/创建/保存/删除/等),每个操作都有可能卡住整个 UI。下面是调用 service.GetAll() 的简单实现示例,这可能需要“很长”的时间(超过几百毫秒):

private void btnRefresh_Click(object sender, RoutedEventArgs e)
{
vm.Users.Clear();
foreach (var user in service.GetAllUsers())
vm.Users.Add(user);
}

(另外:我很想知道为什么 ListAddRangeObservableCollection 没有。)

BackgroundWorker 来拯救:

private void btnRefresh_Click(object sender, RoutedEventArgs e)
{
var worker = new BackgroundWorker();

worker.DoWork += (s, e) =>
{
Dispatcher.BeginInvoke((Action)delegate() { btnRefresh.IsEnabled = false; });
e.Result = service.GetAllUsers();
};

worker.RunWorkerCompleted += (s, e) =>
{
vm.Users.Clear();
foreach (var user in (List<UserDto>)e.Result)
vm.Users.Add(user);
Dispatcher.BeginInvoke((Action)delegate() { btnRefresh.IsEnabled = true; });
};

worker.RunWorkerAsync();
}

(旁白:上面的代码已经过简化,但这就是它的要点。)

使用 BackgroundWorker 的代码完全符合我的要求。该应用程序始终保持响应,并且该按钮在通话期间处于禁用状态。但是,这意味着要为用户可能执行的每个可能操作添加 15 行。

说它不是这样的。

最佳答案

不,BackgroundWorker 不是唯一的方式,但它是一种方式。任何其他方式也将包括某种形式的异步构造,需要使用 Dispatch.BeginInvoke 来更新 UI。例如,您可以使用 ThreadPool:

ThreadPool.QueueUserWorkItem(state => {
Dispatcher.BeginInvoke((Action)delegate() { btnRefresh.IsEnabled = false; });
foreach (var user in service.GetAllUsers())
vm.Users.Add(user);
Dispatcher.BeginInvoke((Action)delegate() { btnRefresh.IsEnabled = true; });

});

如果这是一个重复出现的模式(一个按钮将触发一些应该异步执行的操作,在此过程中按钮被禁用)您可以将其包装到一个方法中:

private void PerformAsync(Action action, Control triggeringControl)
{
ThreadPool.QueueUserWorkItem(state => {
Dispatcher.BeginInvoke((Action)delegate() { triggeringControl.IsEnabled = false; });
action();
Dispatcher.BeginInvoke((Action)delegate() { triggeringControl.IsEnabled = true; });
});
}

...并称它为:

PerformAsync(() => 
{
foreach (var user in service.GetAllUsers())
vm.Users.Add(user);
}, btnRefresh);

作为使用 ThreadPool 的一个选项,您也许还应该查看 Task Parallel Library .

执行此操作时,您应该注意如何处理 UI 状态。例如,如果您有多个控件触发同一操作,请确保在操作过程中禁用所有控件。

注意:这些只是快速的想法。该代码尚未经过测试,因此可能包含错误。它更应该被视为讨论 Material 而不是最终解决方案。

关于c# - BackgroundWorker 是保持 WCF/WPF 应用程序响应的唯一方法吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5327096/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com