我有一个Windows窗体应用程序。按下某个按钮后,我想在后台做一些事情。
//---------- 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;
}
但是,当我尝试在run方法中访问MyWorker的对象时,由于它在不同的线程中运行,因此存在一些复杂性。这里会有什么模式?我在考虑类似的事情:
//---------- 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);
}
但我无法通过其他方法访问MyWorker。提前谢谢..我很困惑。
答案 0 :(得分:3)
您不应完全按照Task.Run
(或StartNew
)实施方法;相反,使用Task.Run
调用方法:
async void DoSomething(object sender, EventArgs e)
{
var task = Task.Run(() => MyWorker.Run());
await task;
}
这样,您可以从多种方法访问MyWorker
...当然还有多个线程。然后由你来应用适当的同步。
在旁注中,您不需要在现代应用中使用Invoke
或BeginInvoke
;总有优越的解决方案。例如,await
将自动返回UI线程上下文。同样,Progress<T>
可以自动同步到UI上下文。
答案 1 :(得分:-2)
您可以自定义此方法:
var myTasks = new ConcurrentBag<Task>();
var myResults = new ConcurrentBag<int>();
并使用它:
myTasks.Add(Task.Factory.StartNew(() =>
{
//do something
myResults.Add(5);
});