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

    }

詳細については、BackgroundWorker の使用方法に関する MSDN 記事へのリンクを次に示します。これを含めるよう提案してくれた Henk Holterman に感謝します。

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

于 2010-08-02T19:39:35.840 に答える
1

In the "// Update UI here", make sure to use Control.Invoke to actually do the work -- it's imperative that the UI only be "touched" by the UI-thread, and this only happens when you use Control.Invoke.

于 2010-08-02T19:33:42.917 に答える
1

BeginInvokeそしてInvoke、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 に答える