如何使用多线程处理来自多个线程的多个返回值?

时间:2018-08-28 15:14:41

标签: c# multithreading

我正在尝试将我的单线程函数转换为多线程函数。我一直在阅读线程,但是不确定如何为阵列中的每个服务器启动线程,同时等待线程完成并从每个线程接收返回值所需的结构正确可以解析返回值数据之前的一个。

所以操作顺序应该是

  1. 为每个服务器名称启动一个新线程
  2. 每个线程结束时应从功能runPowerShellScript(server))中接收输出
  3. 等待每个线程结束,然后组织数据。如果我有5台服务器,我将有5个具有返回值的不同变量

另外,OS /编译器如何处理这样的情况,即每个打开的线程的返回变量(returnVal)名称都相同?我知道这对于在课堂上教过的人来说可能是基本的,因为我是自学成才的,所以我不确定该怎么做。

    private void Run_Click(object sender, EventArgs e)
    {
        string[] servers = { "server1", "server2", "server3", "server4", "server5" };

        foreach (string server in servers)
        {
            Collection<PSObject> returnVal = new Collection<PSObject>();
            Thread psquery = new Thread(() => returnVal = runPowerShellScript(server)); // lambda expression assigns return value to function
            psquery.Start();
            psquery.Join(); // waits for thread to finish
        }

        // process data here
    }

2 个答案:

答案 0 :(得分:1)

您可以使用TAP模式(https://docs.microsoft.com/en-us/dotnet/standard/asynchronous-programming-patterns/task-based-asynchronous-pattern-tap)。由于您要等待每个任务完成,因此可以采用以下方法:

private async void Run_Click(object sender, EventArgs e)
{
     string[] servers = { "server1", "server2", "server3", "server4", "server5" };

     var returnVal = new List<PSObject>();

     foreach (var server in servers)
     {
        var result = await Task.Run(() => runPowerShellScript(server));
        returnVal.Add(result);
     }

     // process data here
}

每个任务都将等待结果并添加到returnVal list中,以便您可以在代码中使用结果。

答案 1 :(得分:0)

这里有一篇文章,供您进一步阅读有关Stackoverflow的选项:article

对于使用您的问题/示例的代码示例,请使用PTL API:

    /// <summary>
    /// I didn't test this, I am assuming you can work out the details
    /// (I prefer this way)
    /// </summary>
    /// <returns></returns>
    private void Run_Click(object sender, EventArgs e)
    {
        var response = new ConcurrentBag<PSObject>();
        var exceptions = new ConcurrentQueue<Exception>();

        string[] servers = { "server1", "server2", "server3", "server4", "server5" };

        try
        {
            Parallel.ForEach(servers, server =>
            {
                response.Add(runPowerShellScript(server));
            });
        }
        catch (AggregateException ae)
        {
            foreach (var e in ae.InnerExceptions)
            {
                exceptions.Enqueue(e);
            }
        }

        if (exceptions.ToList().Any())
        {
            //there are exceptions, do something with them
            //do something?
        }

        try
        {
            // quote:  // process data here
        }
        catch (Exception e)
        {
            // do something with it
        }
    }