Home > Software engineering >  Access non-static control from a static function
Access non-static control from a static function

Time:06-21

I want to access label1 but I can't since it's not static. Also, I can change neither functions to non-static because I need them in the thread. Is there any way to access non-static label1 from static functions?

Set label1 to static? Or is there any way that I can change the functions to non-static and still use it for threads?

PS. In this sample code, it just sets the label's text as "Access Denied" but in my actual code, SetDataStore method will constantly read changing values from a c shared memory and keep updating the label's text.

public partial class Form1 : Form
{
    Thread testThread = new Thread(TestFunction);
    public Form1()
    {
        InitializeComponent();

        testThread.Start();
    }

    static void TestFunction()
    {
        SetDataStore();
    }

    static void SetDataStore()
    {
        // can't access non-static control
        label1.Text = "Access Denied";
    }
}

CodePudding user response:

I think there is a significant lack of understanding of threads and thread safety.

While static methods are by convention thread safe, they do not automatically become so just by being static. You need to ensure they are thread safe. There should be no problem starting a thread at a regular non static member method, but you still need ensure it is safe.

But you are writing an UI program, and accessing UI objects from any thread except the UI thread is illegal. So there is no way to do what your example tries to do.

The correct way would be to move any CPU heavy work to a background thread, and update the UI on the UI thread. For example:


public async void OnButtonpress(...){
   try{
        var result = await Task.Run(OnBackgroundThread);
        label1.Text = result ; // Update UI on UI thread
    }
    catch{
        // handle exceptions
    }
}
private string OnBackgroundThread(){
   // Do CPU heavy work on background thread
   return "Access Denied";
}

CodePudding user response:

I think the problem you're trying to solve is to perform a long running process without blocking your UI and trying to manually kick off a thread that makes use of static methods to do this is the wrong tool. Even if you make your label available to your static method, you'll still need to queue the work on the UI component with InvokeRequired and BeginInvoke etc.

A much better approach is to make use of the Task Asynchronous Pattern. Your form could then look something like this:

public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
        label1.Text = "Loading ...";
    }

    private async void Form1_Load(object sender, EventArgs e)
    {
        await SetDataStoreAsync();
    }

    private async Task SetDataStoreAsync()
    {
        string result = "";
        // await your awaitable process here
        await Task.Delay(1000);

        // If your process isn't awaitable, try make it so.
        // If you can't here's a quick way to place your work on a worker thread and await it.
        await Task.Run(() =>
        {
            System.Threading.Thread.Sleep(5000);
            result = "Access denied";
        });
        

        label1.Text = result;
    }
}
  • Related