我想通过多线程做一些工作,但结果不应该在线程中管理。例如:
private void button1_Click(object sender, EventArgs e)
{
for (int j = 0; j < 2; j++ )
{
ThreadPool.QueueUserWorkItem((o) =>
{
var result = Function1();
BeginInvoke(new Action(() =>
{
Function2(result);
})
);
}
);
}
}
private int Function1()
{
Random rnd = new Random();
Thread.Sleep(1000);
int k = rnd.Next(10, 20);
return k;
}
private void Function2(int i)
{
string s = i.ToString();
Thread.Sleep(2000);
s += i.ToString();
MessageBox.Show(s);
}
通过这段代码,Function1
在多线程中执行,function2()
在从 function1 获取结果后对结果值进行一些处理。
但是,当 Function1() 在多线程中执行并更改 结果
时,Function2
无法正常工作,因为结果被覆盖。那么我该如何解决它呢?
我想我应该将返回值(来自Function1)保存在一个数组中并一一管理它们。有没有更好的办法?
最佳答案
使后台工作尽可能独立并避免副作用确实有很大帮助。
因此,Function1
不应执行任何操作来更改外部状态,并且您不应将其结果设置为表单中的字段或任何位置。这应该很容易修复。
因此,将Function1
的结果存储在局部变量中,而不是字段中。然后将该变量传递给 Function2
,就完成了。一种方法是对局部变量使用闭包:
ThreadPool.QueueUserWorkItem((o) =>
{
var result = Function1(p1, p2, p3, p4, p5);
BeginInvoke(new Action(() =>
{
Function2(result);
})
);
}
);
现在,您的后台工作不再更改共享状态,并且与其他地方发生的任何情况并行执行会更安全。
只需确保 Function1
不会更改不同的共享状态。哦,即使在 Function1
中读取数据时也要小心 - 如果在不同的线程上读取和写入数据,则很容易读取不一致的数据。
当然,这是处理多线程和异步代码的一种相当古老的方法。如果您可以访问 .NET 4.5,那么最好使用新的 async/await 语法,例如像这样的东西:
var result = await Task.Run(() => return Function1(p1, p2, p3, p4, p5));
Function2(result);
当您在表单的事件处理程序中(或更准确地说,在同步上下文中)执行此操作时,它将并行执行 Function1
,并将结果值推回 UI 线程,准备好Function2
。
关于c# - 如何在多线程中获取函数的结果,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26377236/