本文介绍了以有限的并发并行执行的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想在 Silverlight 5 中以有限的并发并行执行异步操作.

I would like to execute async operations in parallel, in Silverlight 5, with limited concurency.

我的代码就像:

    public async void btn_click(object s, RoutedEventArgs e)
    {
        await DoAllWork();
    }

    private async Task DoAllWork()
    {
        //Get work to do
        int[] wrk = new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };

        //Start the tasks
        Task[] tasks = new Task[wrk.Length];
        for (int i = 0; i < wrk.Length; i++)
        {
            int item = wrk[i];
            tasks[i] = WorkSingleItem(item);
        }
        await TaskEx.WhenAll(tasks);
    }

    private async Task WorkSingleItem(int item)
    {
        //a very long operation
        var response = await Request(item);
        await Handle(response);
    }

我找到了这篇文章:http://msdn.microsoft.com/en-us/library/ee789351(v=vs.110).aspx

如何等待我的工作方法,即使用有限并发调度程序"启动所有长时间操作,并且每个项目的工作不依赖于同步上下文以避免在 UI 线程中执行代码...

How can I await my work method, that start all my long operations with the "limited concurrency scheduler", and with each item work not relying on synchronization context to avoid code executed in UI thread...

推荐答案

由于你的长操作是异步处理 I/O,并且限制并发的目的是为了避免 DDoS,那么一个 TaskScheduler 是一个不正确的解决方案.这是因为 TaskScheduler 只控制活动任务(运行或阻塞);当一个任务通过 await 返回给它的调度器时,它不再被认为是活动的".因此,如果您的 I/O 是异步的,则不能使用 TaskScheduler 来防止 DDoS.

Since your long operations deal with I/O asynchronously, and the purpose of the limited concurrency is to avoid a DDoS, then a TaskScheduler is an incorrect solution. This is because a TaskScheduler only controls active tasks (running or blocked); when a task yields back to its scheduler via await, it's no longer considered "active". So, a TaskScheduler can't be used to prevent a DDoS if your I/O is asynchronous.

正确的解决方案是使用类似 兼容信号量:

The correct solution is to use something like an async-compatible semaphore:

public async void btn_click(object s, RoutedEventArgs e)
{
  await Task.Run(() => DoAllWork());
}

private async Task DoAllWork()
{
  int[] wrk = new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
  var semaphore = new AsyncSemaphore(4);

  var tasks = wrk.Select(x => WorkSingleItem(x, semaphore));

  await TaskEx.WhenAll(tasks);
}

private async Task WorkSingleItem(int item, AsyncSemaphore semaphore)
{
  await semaphore.WaitAsync();
  try
  {
    var response = await Request(item);
    await Handle(response);
  }
  finally
  {
    semaphore.Release();
  }
}

这篇关于以有限的并发并行执行的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

09-21 02:17