我有一个程序对数据库进行了一些大量调用,然后更新了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,那么就应该如何进行调用 - 这是正确的吗?我做错了吗?
答案 0 :(得分:3)
使用.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
答案 1 :(得分:1)
在“// Update UI here”中,确保使用Control.Invoke实际完成工作 - UI必须“触及”UI线程,这只有在您使用时才会发生Control.Invoke。
答案 2 :(得分:1)
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 */
}
答案 3 :(得分:0)
我不确定语法..但我更熟悉的语法是:
public delegate object myDelegate(object myParam);
Public class MyClass
{
public static void Main()
{
myDelegate d = new myDelegate(myMethod);
d.BeginInvoke ( new object() );
}
static void myMethod(object myParam)
{
// do some work!!
return new object);
}
}