Solve a cross-threading Exception in WinForms

后端 未结 6 1790
北荒
北荒 2020-12-01 17:14

Presently I\'m working with WinForms(in C#) and I have to run the application in the background. For this purpose I\'m using asynchronous. When I run the application it\'s s

相关标签:
6条回答
  • 2020-12-01 17:45

    Updated from Invoke to begin Invoke

    // you can define a delegate with the signature you want
    public delegate void UpdateControlsDelegate();
    
    public void SomeMethod()
    {
        //this method is executed by the background worker
        InvokeUpdateControls();
    }
    
    public void InvokeUpdateControls()
    {
        if (this.InvokeRequired)
        {
            this.BeginInvoke(new UpdateControlsDelegate(UpdateControls));
        }
        else
        {
            UpdateControls();
        }
    }
    
    private void UpdateControls()
    {
        // update your controls here
    }
    
    0 讨论(0)
  • 2020-12-01 17:46

    The UI changes can be done with Control.Invoke() methods, this cross thread exception can be solved using below code snippet.

    void UpdateWorker()
    {
       //Here ddUser is the user control
       //Action to be performed should be called within { } as like below code
       if (this.ddUser.InvokeRequired)
          ddUser.Invoke(new MethodInvoker(() => { ddUser.Size = new Size(100, 100); }));
    }
    
    0 讨论(0)
  • 2020-12-01 17:57

    Most often, the best way to do this sort of thing with WinForms is to use BackgroundWorker, which will run your work on a background thread, but provide you with a nice clean way to report status back to the UI.

    In a lot of everyday .NET programming, explicitly creating threads or calling .Invoke is a sign that you're not using the framework to its full advantage (of course, there are lots of legitimate reasons to do low-level stuff too, it's just that they're less common that people sometimes realise).

    0 讨论(0)
  • 2020-12-01 17:59

    When making method calls to a control, if the caller is on a different thread than the one the control was created on, you need to call using Control.Invoke. Here is a code sample:

    // you can define a delegate with the signature you want
    public delegate void UpdateControlsDelegate();
    
    public void SomeMethod()
    {
        //this method is executed by the background worker
        InvokeUpdateControls();
    }
    
    public void InvokeUpdateControls()
    {
        if (this.InvokeRequired)
        {
            this.Invoke(new UpdateControlsDelegate(UpdateControls));
        }
        else
        {
            UpdateControls();
        }
    }
    
    private void UpdateControls()
    {
        // update your controls here
    }
    

    Hope it helps.

    0 讨论(0)
  • 2020-12-01 18:04

    A pattern you might find useful is to do a check at the top of functions that interact with the GUI to see whether you are running on the correct thread or not and have the function invoke itself if required. Like this:

        public delegate void InvocationDelegate();
    
        public void DoGuiStuff(){
          if (someControl.InvokeRequired){
            someControl.Invoke(InvocationDelegate(DoGuiStuff));
            return;  
          }
    
          //GUI manipulation here
        }
    

    Using this pattern - if you are on the correct thread when the method is called it doesn't invoke itself, but if you are on a different thread it will invoke itself and then return (so the GUI manipulation logic is only ever called once either way).

    0 讨论(0)
  • 2020-12-01 18:05

    You need to check if Invoke is required for the control you're trying to update. Something like this:

    Action<Control, string> setterCallback = (toSet, text) => toSet.Text = text;
    
    void SetControlText(Control toSet, string text) {
      if (this.InvokeRequired) {
        this.Invoke(setterCallback, toSet, text);
      }
      else {
        setterCallback(toSet, text);
      }
    }
    
    0 讨论(0)
提交回复
热议问题