我有一个程序,它对数据库进行一些繁重的调用,然后更新UI。这会导致问题,因为在大多数情况下,这意味着UI没有响应。因此,我决定将访问数据库和更新UI的函数调用放在一个单独的线程中,所以现在我有了如下内容:
private delegate void CallAsyncDelegate();
private void CallGetDBValues()
{
// Call GetDatabaseValues in new thread
CallAsyncDelegate callGetDatabaseValues = new
CallAsyncDelegate(GetDatabaseValues);
BeginInvoke(callGetDatabaseValues);
}
private void GetDatabaseValues()
{
// Get lots of data here
// Update UI here
}
...然而,这似乎对UI没有任何影响。我在某处读到,如果要在单独的线程中运行的代码需要更新UI,那么应该如何进行调用-这是正确的吗?我做错了什么吗?
发布于 2010-08-03 03:39:36
使用.NET框架中内置的BackgroundWorker可能会更好。
BackgroundWorker bw = new BackgroundWorker();
bw.DoWork += new DoWorkEventHandler(bw_DoWork);
bw.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bw_RunWorkerCompleted);
bw.ProgressChanged += new ProgressChangedEventHandler(bw_ProgressChanged);
bw.WorkerReportsProgress = true;
void bw_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
// update UI with status
label1.Text = (string)e.UserState
}
void bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
//Check for cancel
if(e.Cancelled)
{
//Handle the cancellation.
{
//Check for error
if(e.Error)
{
//Handle the error.
}
// Update UI that data retrieval is complete
}
void bw_DoWork(object sender, DoWorkEventArgs e)
{
// Get data
//foreach to process data
//Report progress
bw.ReportProgress(n, message);
}下面是关于如何使用BackgroundWorker的MSDN文章的链接,以了解更多详细信息。感谢Henk Holterman提出的建议,包括以下内容:
http://msdn.microsoft.com/en-us/library/cc221403%28VS.95%29.aspx
发布于 2010-08-03 03:33:43
在"// Update UI here“中,确保使用Control.Invoke来实际执行工作--只有在使用Control.Invoke时,UI才会被UI线程”触摸“,这是必须的。
发布于 2010-08-03 03:41:01
BeginInvoke和Invoke意味着在UI线程上运行代码。在这种情况下,如果您从UI线程调用CallGetDBValues(),您将不会获得任何东西。
通常,您将创建一个BackgroundWorker或后台线程来执行繁重的任务,它将向UI线程回调需要更新的值。
BackgroundWorker可能是更好的解决方案(参见Robaticus的答案),但这里是一个后台线程版本。
private delegate void CallAsyncDelegate();
private void button_Click( object sender, EventArgs e )
{
Thread thread = new Thread( GetDBValues );
thread.IsBackground = true;
thread.Start();
}
private void GetDBValues()
{
foreach( ... )
{
Invoke( new CallAsyncDelegate( UpdateUI ) );
}
}
private void UpdateUI()
{
/* Update the user interface */
}https://stackoverflow.com/questions/3391099
复制相似问题