开发者

WinForms equivalent of performSelectorOnMainThread in Objective-C

开发者 https://www.devze.com 2022-12-23 09:45 出处:网络
I haven\'t done much multithreading before and now find the need to do some background work and keep the UI responsive. I have the following code.

I haven't done much multithreading before and now find the need to do some background work and keep the UI responsive. I have the following code.

data.ImportProgressChanged += new 
     DataAccess.ImportDelegate(data_ImportProgressChanged);

Thread importThread = new Thread(
       new ThreadStart(data.ImportPeopleFromFAD));
importThread.IsBackground = true;
importThread.Start();

void data_ImportProgressChanged(int progress)
{
    toolStripProgressBar.Value = progress;
}

//In my data object I have 
public void ImportPeopleFromFAD()
{
    ImportProgressChanged(someInt);
}

But the UI doesn't get updated since the ImportProgressChanged() call is made on the background thread. In objective C I know you can use performSelectorOnMainThread and pass it a method to call usi开发者_JAVA百科ng the main thread. What is the equivalent way of calling ImportProgressChanged() from the main thread?


(Assuming Windows Forms.) You can use Control.Invoke or Control.BeginInvoke - but a cleaner way may be to use BackgroundWorker to start with.

In WPF you'd use a Dispatcher instead of Control.Invoke, btw. See this WPF threading model guide for more details.

EDIT: Personally I probably wouldn't bother testing InvokeRequired first - I'd just call Invoke or BeginInvoke. If you're already "on" the right thread it won't do any significant harm.

For progress bars, however, BackgroundWorker is definitely the way forward.


Instead of updating the GUI, data_ImportProgressChanged should throw an exception when it gets called changes the progressbar.

The shortest change is to use Control.InvokeRequired and .Invoke(), but the Backgroundworker was especially created for this scenario .

If you want to solve it in the data object you will have to make that depend on the GUI so its better to solve this in the handler:

void data_ImportProgressChanged(int progress)
{
    if (toolStripProgressBar.InvokeRequired)
    {
        Action<int> a = new Action(data_ImportProgressChanged);
        toolStripProgressBar.Invoke(a, progress);
    }
    else
        toolStripProgressBar.Value = progress;
}


You already have your answer but I'll add my solution anyway:

void data_ImportProgressChanged(int progress)
{
    if (InvokeRequired)
    {
        BeginInvoke(new Action<int>(data_ImportProgressChanged),progress);
        return;
    }

    toolStripProgressBar.Value = progress;
}
0

精彩评论

暂无评论...
验证码 换一张
取 消