2011-07-25 36 views
0

背景:我曾在表单加载期间调用存储过程。然而,由于这导致了不太理想的用户体验,我把自己的SP调用放入了一个自己的任务中,在Shown事件中。由于这通常是表单显示过程中的最后一个事件,因此与将事件放入表单加载事件相比,它产生了更好的体验。我有:如何在非GUI线程中获得任务完成通知

private void MainForm_Shown(object sender, EventArgs e) 
{ 
    dbCheckTask = Task<bool>.Factory.StartNew(RunSPAndCheckStuff()); 

    // both of below run on the GUI thread. 

    // if I print the thread ID in mycallback it is the GUI thread id 
    dbCheckTask.ContinueWith(mycallback()); 

    // I also tried below. But obviously, that too runs on the GUI thread 
    mycallback(dbCheckTask.Result) 

} 

因为他们开火的GUI线程上,我的启动窗体油漆还没有瞬时也不顺利。如何在不使用事件的情况下在非GUI线程上完成我的任务完成回调?每当任务完成时,如果出现错误,并且只有出现错误(布尔结果返回false),用户才会弹出消息框。在此之前,他可以继续在表单上完成其他与数据库无关的内容。请告知我如何在非GUI线程中获得任务完成回调并显示任务结果。谢谢

+0

这看起来对我来说,它应该已经工作 - 你可以张贴代码或伪代码为myCallBack函数()方法? – Stuart

+0

我相信你可以使用TaskScheduler.Default来获得一个没有绑定到同步上下文的调度器。事实上,您看到此问题意味着TaskScheduler.Current在某个时刻被设置为一个sycnchronized任务调度程序。 –

+0

@Stuart。如果其他人对此问题的建议不起作用,将会发布一些示例代码。thx – Gullu

回答

1

我个人使用BackgroundWorker。一个办法让你的回调任务线程上运行,将修改您的方法调用和任务的创建如下:

private void MainForm_Shown(object sender, EventArgs e) 
{ 
    dbCheckTask = Task<bool>.Factory.StartNew(() => RunSPAndCheckStuff(mycallback)); 
    ... 
} 

private bool RunSPAndCheckStuff(Action<bool> callback) 
{ 
    bool result = false; 
    // Do stuff 
    callback(result); 
    return result; 
} 
+0

我认为这将工作。将尝试并发回thx – Gullu

+0

thx先生。作品。 – Gullu

+0

虽然这确实起作用,后台线程将被阻止,等待SP返回。每当处理任何类型的I/O时,都应该使用适当的异步API。 – BFree

1

你应该考虑使用异步API的,而不是调用同步版本在后台线程:

http://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqlcommand.beginexecutenonquery.aspx

到的优点是没有线程将被阻止,我相信回调将在ThreadPool线程上调用,例如不在GUI线程上。从那里你可以用Invoke/BeginInvoke将任何GUI调用封送回GUI线程。

+0

从来没有想过这样做。好的提示。我确信有一个tpl的方式来做到这一点。 thx – Gullu

+0

是的,这可以很容易地使用FromAsync方法完成:http://msdn.microsoft.com/en-us/library/dd321311.aspx – BFree

0

为什么不这样做:

Task.Factory.StartNew(()=>WorkerMethod()); 

,并定义WorkerMethod()为:

void WorkerMethod() 
{ 
    RunSPAndCheckStuff(); // this blocks until finished 
    DoSomeMoreStuff(); // then this continuous 
} 

否则,请提供您想要完成什么的更多细节。

3

所有这些东西在可以下载的异步语言扩展here和主页here中寻址最好。

它引入了asyncawait关键字C#和VB,可以让你写的轻松,即使在一个单一的方法来回切换UI和后台线程之间的代码。编译器会将其转换为任务,延续,错误捕捉等等,而不必担心这些。你会感兴趣的例子是:

public async void AsyncSwitchToCPU() { 
    Console.WriteLine("On the UI thread."); 

    // Switch to a thread pool thread: 
    await new SynchronizationContext().SwitchTo(); 

    Console.WriteLine("Starting CPU-intensive work on background thread..."); 
    int result = DoCpuIntensiveWork(); 
    Console.WriteLine("Done with CPU-intensive work!"); 

    // Switch back to UI thread 
    await Application.Current.Dispatcher.SwitchTo();     

    Console.WriteLine("Back on the UI thread. Result is {0}.", result); 
} 

public int DoCpuIntensiveWork() 
{ 
    // Simulate some CPU-bound work on the background thread: 
    Thread.Sleep(5000); 
    return 123; 
} 

这甚至有一个上线许可证(有一些保留从MS)。非常优雅的东西从F#借用。

RGDS格特 - 扬

+0

哇。整齐的东西。但有点矫枉过正,因为我的简单需求。我会阅读这个。谢谢 – Gullu

相关问题