1

我有一个程序对数据库进行大量调用,然后更新 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,那么这就是应该进行调用的方式 - 这是正确的吗?难道我做错了什么?

4

4 回答 4

3

BackgroundWorker使用.NET 框架的内置功能可能会为您提供更好的服务。

    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);

    }

这是 MSDN 文章的链接,了解如何使用 BackgroundWorker 以获取更多详细信息。感谢 Henk Holterman 提出的建议:

http://msdn.microsoft.com/en-us/library/cc221403%28VS.95%29.aspx

于 2010-08-02T19:39:35.840 回答
1

在“// Update UI here”中,确保使用 Control.Invoke 来实际完成工作 - UI 必须只被 UI 线程“触摸”,并且只有在使用 Control.Invoke 时才会发生这种情况.

于 2010-08-02T19:33:42.917 回答
1

BeginInvokeInvoke表示在 UI 线程上运行代码。在这种情况下,如果您CallGetDBValues()从 UI 线程调用,您将不会获得任何东西。

通常,您将创建一个BackgroundWorker或后台线程来完成繁重的工作,并将调用回 UI 线程需要更新的值。

ABackgroundWorker可能是更好的解决方案(请参阅 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 */
}
于 2010-08-02T19:41:01.123 回答
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);
    }
}
于 2010-08-02T19:53:57.230 回答