当前,我有一个包含一堆ID的列表字符串ID,一个以空开头并填充对象的List对象,一个函数返回一个对象getObject(string id),该对象获取给定ID字符串的对象。有没有一种方法可以轻松地对此进行线程化,而不必使用Threading类进行串行处理呢?线程似乎没有办法返回对象,因为它们使用了void函数。
答案 0 :(得分:0)
使用:
var task = Task.Run<object>(() => /** your delegate returning an object **/)
然后可以使用Result
,Wait
或await
关键字(最好的首选等待时间)来处理它。
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线程),然后,当它完成时,我醒来并弹出消息框。