0

How can I call the function WriteLog from another thread or class that affects a form control?

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

namespace DockerManager
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
            CheckForIllegalCrossThreadCalls = false;
        }

        public void WriteLog(string text, bool withdate = true)
        {
            if (withdate)
            {
                txtDebugLog.Text = string.Format("{0}\r\n{1}", DateTime.Now.ToString("HH:mm:ss") + ": " + text, txtDebugLog.Text);
            }
            else
            {
                txtDebugLog.Text = string.Format("{0}\r\n{1}", text, txtDebugLog.Text);
            }
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            ControlsWorker.RunWorkerAsync();
        }

        private void Controls_DoWork(object sender, System.ComponentModel.DoWorkEventArgs e)
        {
            while (!ControlsWorker.CancellationPending)
            {
                WriteLog("Testing msg");

                Thread.Sleep(500);
            }

            e.Cancel = true;
        }
    }
}

I want to modify txtDebugLog.Text from a backgroundworker and also from a class like this:

class TestClass
{
    Form1.WriteLog("Hello");        
}

My idea was doing something like this:

public class TestClass
{
    Form1 form = new Form1();

    public TestClass(byref form)
    {
        this.form = form;
        this.form.WriteLog("Hello");
    }       
}

But it's not possible to send a byref argument to a constructor

I'm using this line for calling the method from the backgroundworker and it's working but I don't want to use such a dirty method:

CheckForIllegalCrossThreadCalls = false;

And it's not solving the part of calling the method from another class...

kuhi
  • 531
  • 5
  • 23
  • There is a very very good reason that `IllegalCrossThreadCalls` are illegal. By turning that check off, all you are doing is increasing the likelyhood that something really bad happens (possibly worse than the application crashing). Instead you should look at Marsheling the effects back to the UI thread. It is "possible" to achieve what you are asking for. But it would be slow, prone to crashing and extremely complex (diving deep into Win32/GDI calls). – Aron Oct 08 '20 at 09:23
  • In short, you do not stick your head into a running car engine. All you did was disable the safety switch that turns off the engine when you stick your head in... – Aron Oct 08 '20 at 09:28
  • As I already mention in my question, I already know why CheckForIllegalCrossThreadCalls is a dirty fix, I'm just asking for an alternative solution – kuhi Oct 08 '20 at 09:40
  • 1
    As I said, Marshel the work back to the UI thread. I can't advise you how to do this. Since there are 1001 ways to do it, but without knowing what you are trying to achieve it is pointless for me to point you in a direction. My advise for you is, unless you are CPU bound, forget about threading completely, and just use `async`/`await`, and stay on the UI thread for everything. – Aron Oct 08 '20 at 10:12

0 Answers0