-1

Apologies as I know cross-thread operations have been addressed elsewhere, but all I see are fragments and can't quite figure out where to apply the solutions correctly. So I have distilled this problem to it's most basic essence in the hope that me and anybody else who comes across this can see a complete solution without a lot of support code to wade through or fragments with limited context. I have looked at various posts such as here, here and here but can't quite place the solutions in context.

I have created a Windows Forms project with a single button and textbox. In the form.cs file here is the complete code to demonstrate the problem:

using System;
using System.Windows.Forms;
using System.Threading;

namespace SampleEventTest
{
public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
    }

    private void Button1_Click(object sender, EventArgs e)
    {
        new Thread(() =>
        {
            Thread.CurrentThread.IsBackground = true;
            TestClass();
        }).Start();
    }
    private void TestClass()
    {
        TestEvent tv = new TestEvent();
        tv.OnClsConnect += new TestEvent.clsConnect(OnConnected);
        tv.DoSomethingThread();
    }
    public void OnConnected(string str)
    {
        textBox1.Text = str;
    }
}
public class TestEvent
{
    public delegate void clsConnect(string str);
    public event clsConnect OnClsConnect;

    public void DoSomethingThread()
    {
        if (OnClsConnect != null)
        {
            OnClsConnect("Thread run");
        }
    }

}
}

Click the button and you will get the "Cross thread operation not valid" error. How does one properly fix this code? TIA

ds_practicioner
  • 733
  • 8
  • 20
  • You have to tell that you want to execute code on UI thread. In order to do that you invoke method `Dispatcher.CurrentDispatcher.Invoke` which executes a job on UI thread. All of this is because UI elements can only be updated from UI thread. This is by design and you have to stick to it. – FCin Sep 15 '19 at 18:11
  • The marked duplicate, which comprehensively addresses cross-thread scenarios in Winforms, has as its accepted and highest-voted answer, a code example that is no less direct and clear than the one you posted below. – Peter Duniho Sep 15 '19 at 23:23
  • I looked at the example you posted. It is a code snippet, precisely what I was trying to avoid here. In addition mine has a separate class as opposed to just another thread. I respectfully disagree. – ds_practicioner Sep 16 '19 at 03:19
  • Actually the only method you should be concerned with is `void OnConnected(string str)`. And handling UI properties is very well described in the duplicate. You cannot avoid invoking dispatcher. – FCin Sep 16 '19 at 06:20

2 Answers2

0

Basically you can use the BackgroundWorker Control. here is a quick link. also here is an anther link which helps you.

also please read this:

How to: Make thread-safe calls to Windows Forms controls

S.A.Parkhid
  • 2,772
  • 6
  • 28
  • 58
0

H/T to S.A. Parkhid for this link.

Here is the solution: modify the method OnConnected to the following:

    public void OnConnected(string str)
    {
        if (textBox1.InvokeRequired)
        {
            var d = new TestEvent.clsConnect(OnConnected);
            textBox1.Invoke(d, new object[] { str });
        }
        else
        {
            textBox1.Text = str;
        }
    }
ds_practicioner
  • 733
  • 8
  • 20