时间:2019-03-17 标签:c#BeginInvoke问题

发布于 2024-09-12 16:58:58 字数 602 浏览 0 评论 0原文

我有一个程序,可以对数据库进行大量调用,然后更新用户界面。这会导致问题,因为在大多数情况下,这意味着 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,那么这就是应该进行调用的方式 - 这是正确的吗?我做错了什么吗?

I have a program that makes some hefty calls to the database and then updates the UI. This is causing problems because for most of the time it means that the UI in not responsive. I therefore decided that I wanted to put the function calls that access the database and update the UI in a separate thread, so now I have something like this:

 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

 }

 ...

However, it seems to make no difference whatsoever to the UI. I read somewhere that if the code to be run in a separate thread needed to update the UI then this was how the call should be made - is this correct? Am I doing something wrong?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

莫言歌 2024-09-19 16:58:58

使用 .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

You may be better served using the BackgroundWorker that is built-in to the .NET framework.

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

    }

Here's a link to the MSDN article on how to use the BackgroundWorker for additional details. Thanks to Henk Holterman for the suggestion to include this:

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

我喜欢麦丽素 2024-09-19 16:58:58

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

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.

半寸时光 2024-09-19 16:58:58

BeginInvokeInvoke 表示在 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 */
}

BeginInvoke and Invoke means to run the code on the UI thread. In this case if you are calling CallGetDBValues() from the UI thread you are not going to gain anything.

Usually you will create a BackgroundWorker or background thread that will do the heavy lifting and it will Invoke back to the UI thread the values that need to be updated.

A BackgroundWorker will probably be the better solution (see Robaticus's answer), but here is a background thread version.

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 */
}
天赋异禀 2024-09-19 16:58:58

我不确定语法......但我更熟悉的语法是这样的:

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

I'm not sure of the syntax.. but the sytax I'm more familiar with is something like:

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);
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文