c# - 如何在多线程中获取函数的结果

标签 c# multithreading

我想通过多线程做一些工作,但结果不应该在线程中管理。例如:

    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/

相关文章:

c# - 高效的纯文本模板引擎

java - 创建比请求更多的线程

java - 调用start()之后,为什么线程的构造函数返回到main(),而没有将控制权转发给run()方法?

c - 什么时候应该使用 select 与多线程进行比较?

c - 如何使用 pthread 并发操作数据?

c# - 传入的值必须是枚举基类或枚举的底层类型,例如 Int32.Parameter name : value

c# - .NetCore - 网络驱动器上的 FileSystemWatcher,不安全代码 Win32 API 崩溃

c# - 通过 id 获取项目并使用自动映射器将其标题映射到字符串

c# - 在基类中实现 IXmlSerializable 时如何恢复到 'default' XML 序列化?

python - 为什么 time.clock 给出的耗时比 time.time 长?