C# 运行异步任务并调用winform控件
如果您有此代码:C# 运行异步任务并调用winform控件,c#,winforms,asynchronous,task,C#,Winforms,Asynchronous,Task,如果您有此代码: Task[] tasks = new Task[3]; int index = 0; foreach (KeyValuePair<string, int> packageId in PackageIds) { await Task.Run(() => _logger.Log(packageId.Key)); tasks[index] = Task.Factory.StartNew(() => { Log(pa
Task[] tasks = new Task[3];
int index = 0;
foreach (KeyValuePair<string, int> packageId in PackageIds)
{
await Task.Run(() => _logger.Log(packageId.Key));
tasks[index] = Task.Factory.StartNew(() =>
{
Log(packageId.Key);
});
index++;
}
Task.WaitAll(tasks);
_logger.Log("all done");
当我运行它时,我可以看到代码试图调用listView1。但在那之后,应用程序将挂起,根本无法继续。当我删除Log()并再次运行它时,它工作得非常好
如何在日志记录中运行此代码?您正在以一种危险的方式使用InvokeRequiered/Invoke模式 问题是您使用
invokererequired
检查线程是否可以从ListView1调用函数。如果不是,则不使用Invoke调用ListView1函数,而是调用自己的函数(this.Log)
实现此模式的正确方法是检查您自己的表单是否需要调用。询问:this.InvokeRequired而不是listview1.InvokeRequired:
class MyForm : Form
{
...
private void MyEventHandler(object sender, ...)
{
if (this.InvokeRequired)
{
Invoke(new MethodInvoker( () => this.MyEventHandler(sender, ...));
}
}
else
{
ProcessMyEvent(...);
}
如果使用调试器单步执行此函数,您将看到需要调用,因此再次调用同一函数,之后不再需要调用
顺便说一句,使用
MethodInvoker
而不是Action
的原因在中给出,您正在以危险的方式使用InvokeRequiered/Invoke模式
问题是您使用invokererequired
检查线程是否可以从ListView1调用函数。如果不是,则不使用Invoke调用ListView1函数,而是调用自己的函数(this.Log)
实现此模式的正确方法是检查您自己的表单是否需要调用。询问:this.InvokeRequired而不是listview1.InvokeRequired:
class MyForm : Form
{
...
private void MyEventHandler(object sender, ...)
{
if (this.InvokeRequired)
{
Invoke(new MethodInvoker( () => this.MyEventHandler(sender, ...));
}
}
else
{
ProcessMyEvent(...);
}
如果使用调试器单步执行此函数,您将看到需要调用,因此再次调用同一函数,之后不再需要调用
顺便说一句,使用
MethodInvoker
而不是Action
的原因在中给出。显然,您有无限循环/递归-Log
函数将永远调用自己,以防listView1.InvokeRequired=true
如何使用日志运行此代码?-您试图通过记录来自另一个线程的消息来实现什么?为什么不在等待后在listview的foreach
循环中简单地添加日志消息呢?现在的代码完全没有理由使用任务。所有的事情都是在UI线程上完成的。如果没有一个好的线程,就不可能知道如何最好地处理您的场景。也就是说,你发布的代码是各种各样的错误。最大的问题(很可能是挂起的原因)是您调用了Task.WaitAll()
,而(显然)在其他线程中执行的代码最终会希望调用Control.Invoke()
,并使用正在阻塞的线程。除此之外,还不清楚你为什么要费心处理任务之类的事情。这似乎没有什么好处,只会让你感到困惑。很明显,你有无限循环/递归-Log
函数将永远调用自己,以防listView1.invokererequired=true
如何使用日志运行此代码?-您试图通过记录来自另一个线程的消息来实现什么?为什么不在等待后在listview的foreach
循环中简单地添加日志消息呢?现在的代码完全没有理由使用任务。所有的事情都是在UI线程上完成的。如果没有一个好的线程,就不可能知道如何最好地处理您的场景。也就是说,你发布的代码是各种各样的错误。最大的问题(很可能是挂起的原因)是您调用了Task.WaitAll()
,而(显然)在其他线程中执行的代码最终会希望调用Control.Invoke()
,并使用正在阻塞的线程。除此之外,还不清楚你为什么要费心处理任务之类的事情。这似乎没有什么好处,只会让你感到困惑。