Reputation: 7198
I have a windows forms application. I want to do something in background after pressing some button.
//---------- MyWorker::Run
public Task Run()
{
WorkerTask = Task.Factory.StartNew(() =>
{
//Access MyWorker's properties etc. causes complications as it runs from
// a different thread and I need to use InvokeRequired etc. but not everything has Invoke method implemented.
}, TokenSource.Token, TaskCreationOptions.LongRunning, TaskScheduler.Default);
return WorkerTask;
}
//---------- Form event
async void DoSomething(object sender, EventArgs e)
{
var task = MyWorker.Run();
await task;
}
However there are some complications when I try to access MyWorker's objects in the run method as it runs in a different thread. What pattern would be prefered here? I was thinking about something like:
//---------- Form event
async void DoSomething(object sender, EventArgs e)
{
Task.Factory.StartNew(() =>
{
var MyWorker1 = new MyWorker(...);
// Worker is synchronous here
MyWorker1.Run();
}, TokenSource.Token, TaskCreationOptions.LongRunning, TaskScheduler.Default);
}
But I wouldn't be able to access MyWorker from other methods. Thanks in advance .. I'm confused.
Upvotes: 0
Views: 92
Reputation: 456322
You shouldn't implement a method entirely in terms of Task.Run
(or StartNew
); instead, call the method with Task.Run
:
async void DoSomething(object sender, EventArgs e)
{
var task = Task.Run(() => MyWorker.Run());
await task;
}
This way you can access MyWorker
from multiple methods... and multiple threads, of course. It's up to you to apply appropriate synchronization then.
On a side note, you shouldn't ever need to use Invoke
or BeginInvoke
in modern apps; there are always superior solutions. For example, await
will return to the UI thread context automatically. Similarly, Progress<T>
can synchronize to the UI context automatically.
Upvotes: 3
Reputation: 828
You can customize this approach:
var myTasks = new ConcurrentBag<Task>();
var myResults = new ConcurrentBag<int>();
and use it like:
myTasks.Add(Task.Factory.StartNew(() =>
{
//do something
myResults.Add(5);
});
Upvotes: -2