我希望在额外的线程中执行result
后可以访问Heavy Process
(重过程的返回结果),因为它主要是在进程UI期间不希望的生效了,
完成该过程后,可以使用result
在一些搜索过程中,查看我的文章,我得到了几种方法到 如果发生这种情况,请提供您在类似情况下了解或使用的最佳方法
这是一个我想以最佳方式处理的样本:
public ACollection DoProcess(Document docProcess)
{
ACollection result = new ACollection ();
ThreadStart threadStart = delegate
{
result = MyProcess(docProcess);
};
var threadProcess = new Thread(threadStart);
threadProcess.Start();
return result ;
}
其他可能的方法可能是IAsyncResult,BackgroundWorker,使用定时器和检查状态,而不是将结果返回到处理它的方法并将其报告给UI,直接以线程安全的方式将其发送到我们的UI控件。 ..
请在类似情况下提出您自己的意见和样本, 提前谢谢
编辑3:方法 - 基于Brian的答案
LenzCollection myResultCollection = new LenzCollection();
TaskScheduler ui = TaskScheduler.FromCurrentSynchronizationContext();
Task.Factory.StartNew(() =>
{
myResultCollection = DoCollect(docProcess);
//Task.WaitAll();
return myResultCollection;
}).ContinueWith((task =>
{
myResultCollection = task.Result;
}), ui);
return myResultCollection;
它仍然没有等待,也没有给出所需的结果
答案 0 :(得分:2)
只需实现一个在执行方法之前注册的事件。然后让方法在完成时引发事件。
例如:
public delegate void MyEventHandler(string result);
public class MyClass
{
public event MyEventHandler MyEvent;
private void Event(string result)
{
MyEventHandler handler = MyEvent;
if(handler != null)
handler(result);
}
public void DoSomethingLong()
{
//Do something
Event("Finish");
}
}
现在您可以像
一样运行它MyClass.Event += MyEventHandler(On_Event);
Thread t = new Thread(MyClass.DoSomethingLong);
t.Start();
void On_Event(string result)
{
//Get executed when finished;
}
调用UI线程的示例
void On_Event(string result)
{
if(this.InvokeRequired)
{
MyEventHandler handler = new MyEventHandler(On_Event);
Invoke(handler, new object[] { result });
return;
}
// At this point you can access your UI without having Cross-Threaded operation!
}
答案 1 :(得分:2)
在桌面(WinForms / WPF)应用程序中,最好和最简单的方法是BackgroundWorker。它旨在处理这个问题。
答案 2 :(得分:1)
如果您使用.NET Framework 4.0 or +
,则可以在Task.ContinueWith中的其他线程和流程中运行该流程,例如
Process pro = null;
Task.Factory.StartNew(() => {
pro =new Process(..);
pro.Start();
pro.WaitForExit();
}).ContinueWith(..process data recieved from the pro)
编辑
请勿使用while(...)
,而是使用pro.WaitForExit()
希望这有帮助。
答案 3 :(得分:1)
选项#1:
使用Task
类和ContinueWith
方法。
TaskScheduler ui = TaskScheduler.FromCurrentSynchronizationContext();
Task.Factory.StartNew(() =>
{
var result = MyProcess(docProcess);
return result.ToString();
}).ContinueWith((task =>
{
textBox1.Text = task.Result;
}, ui);
您必须记住将正确的同步上下文传递到ContinueWith
方法。您可以使用ui
变量了解我是如何做到的。
选项#2:
使用新的async
和await
关键字。 1
private async void SomeButton_Click(object sender, EventArgs args)
{
textBox1.Text = await Task.Run(() =>
{
var result = MyProcess(docProcess);
return result.ToString();
});
}
显然,这对眼睛来说要容易得多,而且所有的编组和同步环境都适合你。
1 新的关键字将在C#5.0中提供,但您现在可以通过Async CTP使用它们。 CTP使用TaskEx
代替Task
。