具有对象返回的C#线程函数

时间:2018-08-09 18:42:43

标签: c# multithreading

当前,我有一个包含一堆ID的列表字符串ID,一个以空开头并填充对象的List对象,一个函数返回一个对象getObject(string id),该对象获取给定ID字符串的对象。有没有一种方法可以轻松地对此进行线程化,而不必使用Threading类进行串行处理呢?线程似乎没有办法返回对象,因为它们使用了void函数。

3 个答案:

答案 0 :(得分:0)

使用:

var task = Task.Run<object>(() => /** your delegate returning an object **/)

然后可以使用ResultWaitawait关键字(最好的首选等待时间)来处理它。

var returnedObject = await task;

Task处的更多信息:https://msdn.microsoft.com/en-us/library/system.threading.tasks.task(v=vs.110).aspx

答案 1 :(得分:0)

假设getObject(string id)方法是线程安全的并且占用大量CPU(即,它不执行I / O操作),那么PLINQ可能是最佳选择。它会自动完成对输入列表进行分区的所有魔术,将工作负载分配给所有可用的CPU内核,然后将子结果合并回到一个结果列表中。

List<string> ids = new List<string>(new[] { "a", "b", "c", "d", "e", "f" });

List<Object> objects = ids
    .AsParallel()
    .Select(id => getObject(id))
    .ToList();

如果需要,您还可以使用.WithDegreeOfParallelism().WithExecutionMode().WithMergeOptions()扩展方法对其进行配置(但通常在默认选项下效果很好)。

但是如果getObject()方法受I / O约束,那么使用Task可能是更好的选择。

答案 2 :(得分:0)

我正在展示两种方法,一种是“老式”方法,一种是带有任务的方法。两者都在一个简单的WinForms演示应用程序中(只是因为...)

这是老式的方式(将工作显式提交给线程池)。为此,我创建了一个简单的小类:

public class OldFashionedThread
{
    private readonly List<string> _listOfStrings = new List<string>();

    public IEnumerable<string> ListOfStrings => _listOfStrings;
    public Form1 TheForm { get; set; }

    public void DoWork(object state)
    {
        var strings = new[] {"Some", "strings", "go", "here"};
        foreach (var s in strings)
        {
            _listOfStrings.Add(s);
            Thread.Sleep(500);
        }
        TheForm?.Invoke(new Action(TheForm.AlertAllDone));
    }
}

“ AlertAllDone”只是弹出一个消息框,提示“全部完成”

然后,在我的主要表单上,我有:

   private OldFashionedThread _worker;
   private void StartThreadBtn_Click(object sender, EventArgs e)
   {
       _worker = new OldFashionedThread {TheForm = this};
       ThreadPool.QueueUserWorkItem(_worker.DoWork);
   }

   private void AllDoneBtn_Click(object sender, EventArgs e)
   {
       if (_worker != null)
       {
           var result = string.Join(" ", _worker.ListOfStrings);
           MessageBox.Show(result);
       }
   }

我单击StartThreadBtn按钮,等待“完成”消息框出现,然后单击AllDoneBtn按钮。

使用任务,我可以做到这一点(直接在表单的代码中):

   private async void AsTaskBtn_Click(object sender, EventArgs e)
   {
       var strings = await GetStringsAsync();
       var result = string.Join(" ", strings);
       MessageBox.Show(result);
   }

   private async Task<IEnumerable<string>> GetStringsAsync()
   {
       return await Task.Run<IEnumerable<string>>(
           () => {
               var listOfStrings = new List<string>();
               var strings = new[] { "Some", "strings", "go", "here" };
               foreach (var s in strings)
               {
                   listOfStrings.Add(s);
                   Thread.Sleep(500);
               }
               return listOfStrings;
           });
   }

await让我等到工作完成(不占用UI线程),然后,当它完成时,我醒来并弹出消息框。