I'm using a StaTaskScheduler (TPL extension) to open some web browser windows simultaneously and navigate to different sites (using WatiN, but it might as well just be a WebBrowser
).
In my example below I'm running 5 concurrent browsers. Works fine, but it locked the UI thread, so I wrapped my tasks in a BackgroundWorker
. Seems like it does the job, but is it the correct way of handling the issue? Do I need to dispose the worker once I'm done? And finally, is lock (ret)
the correct way of keeping ret
thread safe?
StaTaskScheduler sta = new StaTaskScheduler(5);
BackgroundWorker bw = new BackgroundWorker();
bw.DoWork += (s, ea) =>
{
List<string> ret = new List<string>();
lock (ret)
Task.WaitAll(Util.GetList().Select(row => Task.Factory.StartNew(() =>
{
IEnumerable<string> result = DoUiLockingWork(row.Item1, row.Item2);
ret.AddRange(result);
}, CancellationToken.None, TaskCreationOptions.None, sta)).ToArray());
ea.Result = ret;
};
bw.RunWorkerCompleted += (s, ea) =>
{
List<string> result = ea.Result as List<string>;
if (result != null)
Debug.WriteLine(result.Count);
};
bw.RunWorkerAsync();
2 Answers 2
I would go with Task-based method (if you're using .Net 4.5) instead of the BackgroundWorker
. That will sort out most of your problems.
Something in the vicinities of
async Task<List<T>> yourJobAsync(...)
{
var results = await Task.Run ( () =>
{
//your job.
return jobResults
});
return yourJobAsyncResults
}
-
\$\begingroup\$ Thanks, I actually changed the approach to your suggestion once I noticed that backgroundworkers were obselete. Can this return a result from all the nested tasks, without using
lock
? \$\endgroup\$Johan– Johan2014年06月13日 07:41:49 +00:00Commented Jun 13, 2014 at 7:41 -
1\$\begingroup\$ Yes it can. You must have found out the answer by now but in general
Task<T> would return a
T. If you use
IEnumrable<T>` instead of theList
you should be able to useYield()
to return the task result. Check this Microsoft post aboutyield return
and the example. blogs.msdn.com/b/pfxteam/archive/2008/07/23/8768673.aspx \$\endgroup\$Mehrad– Mehrad2014年06月17日 23:33:20 +00:00Commented Jun 17, 2014 at 23:33
I would make your lock a little more tight:
lock (ret)
{
ret.AddRange(result);
}
But otherwise, looks like an all right implementation.
-
1\$\begingroup\$ Thanks for the input. I also replaced the backgroundworker implementation with a pure
Task
solution. \$\endgroup\$Johan– Johan2014年06月12日 22:38:54 +00:00Commented Jun 12, 2014 at 22:38