我想通过多线程来做一些工作,但是这样做的结果应该不在线程中。例如:
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()在多个线程中执行并更改了
result
时,由于覆盖了结果,因此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/