Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/wpf/14.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 将所有非UI代码移动到不同的线程是一个好主意吗?_C#_Wpf_Multithreading_Asynchronous_Async Await - Fatal编程技术网

C# 将所有非UI代码移动到不同的线程是一个好主意吗?

C# 将所有非UI代码移动到不同的线程是一个好主意吗?,c#,wpf,multithreading,asynchronous,async-await,C#,Wpf,Multithreading,Asynchronous,Async Await,我见过许多例子,其中长时间运行的代码是从事件处理程序异步执行的。例如,以下是WPF中按钮单击的事件处理程序: public async void Button_Click(object sender, EventArgs e) { await Task.Run(() => DoWork()); } private int DoWork() { for (int i = 0; i < 10000000; i++) { } return 42; } publi

我见过许多例子,其中长时间运行的代码是从事件处理程序异步执行的。例如,以下是WPF中按钮单击的事件处理程序:

public async void Button_Click(object sender, EventArgs e)
{
    await Task.Run(() => DoWork());
}

private int DoWork()
{
    for (int i = 0; i < 10000000; i++) { }
    return 42;
}
public async void按钮\u单击(对象发送方,事件参数e)
{
等待任务。运行(()=>DoWork());
}
私有内部工作()
{
对于(int i=0;i<10000000;i++){
返回42;
}
如果
DoWork
更复杂,比如说写入数据库,那么多次单击按钮可能会导致多个线程同时尝试写入数据库

如果不使用这些
Task.Run
调用,而是为所有非UI工作创建一个新的
Thread
,该怎么办。任务可以使用类似于
BlockingCollection
的方法在此线程上排队

由于该线程与UI线程是分开的,UI仍然会响应,多次单击按钮会将任务(按顺序)安排到同一线程,从而避免并发问题


这是个好主意吗?

您所说的是一个
队列taskscheduler
,它可以在并行扩展中找到

也就是说,我不会简单地将所有操作排队。虽然您现在有了一个响应良好的UI,但它看起来好像什么都没有发生


我不会犹豫去做一个任务。工厂。开始新的。任务不能保证启动新线程。任务和线程是两件不同的事情。默认的任务调度器足够智能,可以确定所需的资源是否可用于启动任务的新线程。如果您请求立即启动一组任务,队列将自动发生。

对于长时间运行的操作,在大多数情况下使用异步是有意义的:。

与许多事情一样,答案是这取决于
async
/
await
一直以来都是I/O绑定工作的一个很好的解决方案,如注释中所述,并且是现代的首选方法
Task.Run()
也可以

您描述的模式当然可以用来做您想做的事情,并且是保持UI响应性的一个不错的解决方案。将命令排入线程队列之前,请禁用按钮。当您的命令完成时,您可以将按钮状态设置为enabled(启用/禁用按钮),我的意思是在视图模型上更改
bool
值。您的模式绝对适合CPU限制的工作,但同样适合
Task.Run()


您的长时间运行的线程基本上是一个命令队列,如果您需要序列化工作,这将非常有利。因此,这可能是一个“好”主意。

如果要避免多次单击,请禁用该按钮,直到任务完成。我会避免滚动我自己的任务系统。如果它是IO绑定的工作,比如与DB对话,它不应该使用
task。完全运行
,只需一直异步/等待调用即可。如果线程是CPU限制的工作,或者IO没有公开异步方法,那么您只需要启动线程。我支持@RonBeyer:为什么您希望允许用户在不等待前一次单击“结果”的情况下进行多次单击?它是应用程序及其用户的一个值吗?大多数时候,情况并非如此。但这实际上取决于你的场景你为什么要这样做?您希望从您提议的所有工作中获得什么?@Servy我希望在处理UI事件时获得一些一致性。例如,可能有一个类是所有非UI代码的“入口点”(并在自己的线程上执行)。这将使新开发人员更难在UI线程上意外运行非UI代码。我还希望得到这样一个想法,即无论做什么工作,UI都会响应——可能长,也可能短——关键是我甚至不必担心它:它都是在自己的线程上完成的。