从Parallel.ForEach循环的每次迭代产生的异步任务中更新UI

时间:2013-07-24 16:39:39

标签: c# winforms c#-4.0

使用C#4.0,我想知道从下面显示的函数foo()中更新UI的简单方法。我需要更新一些文本框,显示处理的网址数和找到的错误链接数。我对异步任务采取的一般方法是基于我在这里找到的方法:

How to use HttpWebRequest (.NET) asynchronously?

Pseudo Code in my code-behind on the form:

1. populate a ConcurrentBag
2. Task.Factory.StartNew ( () =>
          Parallel.ForEach( ConcurrentBag, (d) =>
           {
             MyAsyncTask(d);

           }

而MyAsyncTask确实:

          <snip>
          try
            {

             IAsyncResult result = myWebRequest.BeginGetResponse (
               new AsyncCallback( foo, state);



            ThreadPool.RegisterWaitForSingleObject(
            result.AsyncWaitHandle,
            new WaitOrTimerCallback(TimeoutCallback),
            state,
            (MSEC * 1000),  
            true
            );

           }
          catch (Exception ex) {}

            private void foo(IAsyncResult result)

            {
            RequestState state = (RequestState)result.AsyncState;
            WebRequest request = state.webRequest;
            HttpWebResponse response = (HttpWebResponse)request.EndGetResponse(result);

            //update the UI ??

            }

2 个答案:

答案 0 :(得分:1)

首先,进行一些代码审查:

  • 您不需要ConcurrentBagList<>会这样做)
  • 您不需要Parallel.ForEach()BeginGetResponse()无法阻止
  • 出于同样的原因,您可能甚至不需要Factory.StartNew()任务
  • 仅使用catch (Exception ex) {}隐藏错误

应用它,你有更简单的代码。

然后,在foo(IAsyncResult result)中,您可以使用Control.Invoke()以正常方式更新用户界面。这已被多次询问和回答like here

答案 1 :(得分:0)

你说:

  

我的任务是写一些迭代100K URL和测试的东西   每个URL是活着的还是死的,让这个过程尽可能少   时间尽可能。

您不需要异步。就这样做:

IEnumerable<string> urls = GetUrls(); //you provide this
var results =
 urls
 .AsParallel().WithDegreeOfParallelism(50)
 .Select(url => CheckUrl(url))
 .ToList();

PLINQ为您处理所有并行和同步。只需提供同步CheckUrl功能。在CheckUrl返回的任何内容中存储可能的异常。

异步最适合WinForms / WPF,或者当你有的线程时。 50不是“吨”。