结果现在显示在 UI 中,直到所有任务完成,即使我在 UI 中添加作为单个任务完成
Result now shown in UI until all tasks are finished even though I am adding in UI as individual task completes
在我的 WPF 应用程序中,我使用任务在单独的线程中进行一些后台处理。之后,当我开始从这些任务中获取结果时,我将结果更新到列表框中。一切都很好,除了每个任务完成时结果没有写入列表框。一旦我的任务数组中的所有项目都完成,所有结果都会写入列表框,因此当我们收到这些结果时,用户基本上看不到结果。相反,他们必须等到最后一个任务完成,然后该列表框中才会显示任何内容。下面是我遇到问题的相关代码的一小部分。整个事情太大了,有很多不相关的东西不能在这里展示。我的代码有什么不对导致延迟吗?
Task<String>[] myTasks = myListWithData.AsParallel().WithDegreeOfParallelism(10).Select( x => RunSomeMethod(x)).ToArray();
// Here I am back at the UI thread
while ( myTasks.Length > 0 )
{
try
{
int i = Task.WaitAny(myTasks);
string Result = myTasks[i].Result;
this.lst1.Items.Add(Result); // result is been added in the listbox. It should be available now??
// here is my logic for removing task with index i from myTasks
}
catch (Exception ex)
{
}
}
// At this point, user gets to see results for all tasks in that listbox
编辑
更新代码,更详细地说明我的任务数组是如何创建的
如果您使用的是 .NET 4.0,则可以使用延续。您不需要 while
循环在 UI 线程中等待获得结果,因为 Task.WaitAny
阻塞了线程。
.NET 4.0
for(var i=0; i < taskCount; ++i)
{
Task.Factory.StartNew(() => // some long running stuff which returns string)
.ContinueWith(t => this.lst1.Items.Add(t.Result),
TaskScheduler.FromCurrentSynchronizationContext());
}
对于 .Net 4.5 或更高版本,您可以按照@SLaks 的建议使用await
。
有很多问题,假设此方法在 UI 线程上运行:
此方法阻塞。 UI 在此方法完成之前不会更新,这将在您完成所有任务之后。
Parallel
/ PLINQ
将使用调用线程作为并行处理线程之一,因此这也会阻塞。
不清楚 RunSomeMethod
做了什么,但正如它 returns Task<string>
的含义是它 returns 没有完成并且异步完成。如果它在返回任务之前实际上没有做任何工作,那么我看不到 MaxDegreeOfParallelism(10)
实际上在做任何事情:所有任务几乎都会立即创建(并在创建时阻塞)。
假设是 .NET 4.5,这可以解决大部分问题。如果需要 Task.WhenAll
(用于附加代码),则调用方法需要标记为 async
:
var tasks = myListWithData.Select(ProcessAsync).ToArray();
await Task.WhenAll(tasks);
// continue
ProcessAsync
定义如下,假设 RunSomeMethod
在 ThreadPool
线程上执行:
private async Task ProcessAsync(string data)
{
var result = await RunSomeMethod(data);
lst1.Items.Add(result);
}
在我的 WPF 应用程序中,我使用任务在单独的线程中进行一些后台处理。之后,当我开始从这些任务中获取结果时,我将结果更新到列表框中。一切都很好,除了每个任务完成时结果没有写入列表框。一旦我的任务数组中的所有项目都完成,所有结果都会写入列表框,因此当我们收到这些结果时,用户基本上看不到结果。相反,他们必须等到最后一个任务完成,然后该列表框中才会显示任何内容。下面是我遇到问题的相关代码的一小部分。整个事情太大了,有很多不相关的东西不能在这里展示。我的代码有什么不对导致延迟吗?
Task<String>[] myTasks = myListWithData.AsParallel().WithDegreeOfParallelism(10).Select( x => RunSomeMethod(x)).ToArray();
// Here I am back at the UI thread
while ( myTasks.Length > 0 )
{
try
{
int i = Task.WaitAny(myTasks);
string Result = myTasks[i].Result;
this.lst1.Items.Add(Result); // result is been added in the listbox. It should be available now??
// here is my logic for removing task with index i from myTasks
}
catch (Exception ex)
{
}
}
// At this point, user gets to see results for all tasks in that listbox
编辑
更新代码,更详细地说明我的任务数组是如何创建的
如果您使用的是 .NET 4.0,则可以使用延续。您不需要 while
循环在 UI 线程中等待获得结果,因为 Task.WaitAny
阻塞了线程。
.NET 4.0
for(var i=0; i < taskCount; ++i)
{
Task.Factory.StartNew(() => // some long running stuff which returns string)
.ContinueWith(t => this.lst1.Items.Add(t.Result),
TaskScheduler.FromCurrentSynchronizationContext());
}
对于 .Net 4.5 或更高版本,您可以按照@SLaks 的建议使用await
。
有很多问题,假设此方法在 UI 线程上运行:
此方法阻塞。 UI 在此方法完成之前不会更新,这将在您完成所有任务之后。
Parallel
/PLINQ
将使用调用线程作为并行处理线程之一,因此这也会阻塞。不清楚
RunSomeMethod
做了什么,但正如它 returnsTask<string>
的含义是它 returns 没有完成并且异步完成。如果它在返回任务之前实际上没有做任何工作,那么我看不到MaxDegreeOfParallelism(10)
实际上在做任何事情:所有任务几乎都会立即创建(并在创建时阻塞)。
假设是 .NET 4.5,这可以解决大部分问题。如果需要 Task.WhenAll
(用于附加代码),则调用方法需要标记为 async
:
var tasks = myListWithData.Select(ProcessAsync).ToArray();
await Task.WhenAll(tasks);
// continue
ProcessAsync
定义如下,假设 RunSomeMethod
在 ThreadPool
线程上执行:
private async Task ProcessAsync(string data)
{
var result = await RunSomeMethod(data);
lst1.Items.Add(result);
}