我想通过多线程来做一些工作,但是这样做的结果应该不在线程中。例如:

    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/

10-11 04:25