0

I'm making a 1:N asynchronous chat program in C# Windows Form.

When the server connection was successful, an attempt was made to change the Enabled property of the Connect button to false.

A cross-thread exception was thrown at this time.

Fortunately I know how to deal with cross-threaded exceptions using Invoke.

So I wrote the code as below.

private void ConnectEnabledChange(bool state)
{
  this.Invoke(new Action(delegate ()
  {
    Connect.Enabled = state;
  }));
}

The problem, however, is that we need to change the properties of the Connect button as well as the properties of several other controls.

try 
{
  server.Start();
  ConnectEnabledChange(false);
  DisConnectEnabledChange(true);
  StateLabelChange("Current State : Connected");
}

...

private void ConnectEnabledChange(bool state)
{
  this.Invoke(new Action(delegate ()
  {
    Connect.Enabled = state;
  }));
}

private void DisConnectEnabledChange(bool state)
{
  this.Invoke(new Action(delegate ()
  {
    DisConnect.Enabled = state;
  }));
}

private void StateLabelChange(string state)
{
  this.Invoke(new Action(delegate ()
  {
    StateLabel.Text = state;
  }));
}

I think Then it seems inefficient to write code like the above every time a cross-thread exception occurs.

Is there any way to integrate them into one?

Or can you make the code simpler?

Thank you for your help.

  • 1
    What you have here is some threaded code that is tightly coupled to the UI. In my view, it would be a good thing to decouple it entirely. You can then, e.g., - raise events that notify status changes, let the subscribers marshal to their Thread, if needed. - Capture the SynchronizationContext, then `Post()` back when you need to notify something. -- The [Progress](https://learn.microsoft.com/en-us/dotnet/api/system.progress-1) class does this all for you, either using a delegate or raising an event, both executed on the Thread that created the `IProgress` object. – Jimi Mar 04 '22 at 11:51
  • 1
    After that, you don't need to know about `this`, the existence of any of its members (Controls, here), just call the `Report()` method and pass any data / state that needs an update. The object that created the delegate knows what to do with the data / states it receives. -- You also have the advantage that your code has no dependencies on specific UI elements, it can be reused elsewhere. -- Note that using `Invoke()` without knowing the state of the UI element invoked, is bound to deadlock at some point. – Jimi Mar 04 '22 at 11:59
  • @Jimi thank you. I'll try to find out more about the things you don't know and study them. –  Mar 05 '22 at 00:52

0 Answers0