在一个线程中比较来自另一个线程的值C#

在一个线程中比较来自另一个线程的值C#,c#,multithreading,comparison-operators,C#,Multithreading,Comparison Operators,我想在我的应用程序中使用BackgroundWorker。我明白了,当我想这样做的时候: buttonStart.Enabled = false; 在主线程中,使用另一个线程,我应该这样做: if (buttonStart.InvokeRequired) { buttonStart.Invoke(new Action(() => buttonStart.Enabled = false)); } else buttonStart.Enabled = false; 但当涉及到比较操作时:

我想在我的应用程序中使用BackgroundWorker。我明白了,当我想这样做的时候:

buttonStart.Enabled = false;
在主线程中,使用另一个线程,我应该这样做:

if (buttonStart.InvokeRequired) { buttonStart.Invoke(new Action(() => buttonStart.Enabled = false)); }
else buttonStart.Enabled = false;
但当涉及到比较操作时:

if(tabControlDbSwitch.SelectedIndex == 0)
它不起作用。 所以,我的问题是:

if ((!tabControlDbSwitch.InvokeRequired && tabControlDbSwitch.SelectedIndex == 0) ||
    (tabControlDbSwitch.InvokeRequired && /*What should I write here?*/))
也许你们给了我一些提示,因为我在多线程方面完全是新手,但我想尽快学习


也就是说,我听说有时候使用BeginInvoke比调用更好,但我不知道为什么以及何时使用。

CheckSelection是您从返回此if代码的函数中调用的函数

        public void CheckSelection()
    {
        if (tabControlDbSwitch.InvokeRequired)
        {
            tabControlDbSwitch.Invoke(new Action(() => { CheckTabSelection(); }));
        }
        else
            CheckTabSelection();
    }

    public void CheckTabSelection()
    {
        if (tabControlDbSwitch.SelectedIndex == 0)
        { 
            // Do my work .....
        }
    }
你说你听说过有时候使用BeginInvoke比调用更好,但我不知道为什么和什么时候。invoke和begininvoke有两种类型:委托和控制。在您的示例中,您使用的是Contol.Invoke

  • Invoke:在同一线程上同步执行
  • Delegate.BeginInvoke:在线程池线程上异步执行意味着在begin invoke中调用的函数将在线程池中的新线程上执行,您可以继续在同一线程上执行操作(并行执行)
  • Invoke:在UI线程上执行,但调用线程将在继续之前等待调用函数的完成
  • Control.BeginInvoke:在UI线程上执行,调用线程不会等待调用的函数完成。 是的,我们建议使用Control.BeginInvoke而不是Control.Invoke,因为您不必担心死锁
例如,如果删除代码

if(tabControlDbSwitch.InvokeRequired)
并始终使用

tabControlDbSwitch.Invoke(new Action(() => { CheckTabSelection(); }));

在某些情况下,此函数是从UI主线程调用的,那么您的代码将挂起并导致死锁。

CheckSelection是您从返回此代码的函数调用的函数

        public void CheckSelection()
    {
        if (tabControlDbSwitch.InvokeRequired)
        {
            tabControlDbSwitch.Invoke(new Action(() => { CheckTabSelection(); }));
        }
        else
            CheckTabSelection();
    }

    public void CheckTabSelection()
    {
        if (tabControlDbSwitch.SelectedIndex == 0)
        { 
            // Do my work .....
        }
    }
你说你听说过有时候使用BeginInvoke比调用更好,但我不知道为什么和什么时候。invoke和begininvoke有两种类型:委托和控制。在您的示例中,您使用的是Contol.Invoke

  • Invoke:在同一线程上同步执行
  • Delegate.BeginInvoke:在线程池线程上异步执行意味着在begin invoke中调用的函数将在线程池中的新线程上执行,您可以继续在同一线程上执行操作(并行执行)
  • Invoke:在UI线程上执行,但调用线程将在继续之前等待调用函数的完成
  • Control.BeginInvoke:在UI线程上执行,调用线程不会等待调用的函数完成。 是的,我们建议使用Control.BeginInvoke而不是Control.Invoke,因为您不必担心死锁
例如,如果删除代码

if(tabControlDbSwitch.InvokeRequired)
并始终使用

tabControlDbSwitch.Invoke(new Action(() => { CheckTabSelection(); }));

在某些情况下,这个函数是从UI主线程调用的,那么您的代码将挂起并导致死锁。

下面是另一种允许Invoke()返回值的方法

通过这种方式,您的代码流动得更好一些:

    private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
    {
        if (GetSelectedIndex(this.tabControlDbSwitch) == 0)
        {
            Console.WriteLine("Success!");
        }
    }

    private delegate int ReturnSelectedIndex(TabControl tb);
    private int GetSelectedIndex(TabControl tb)
    {
        if (tb.InvokeRequired)
        {
            return (int)tb.Invoke(new ReturnSelectedIndex(GetSelectedIndex), new Object[] { tb });
        }
        else
        {
            return tb.SelectedIndex;
        }
    }

下面是另一种允许Invoke()返回值的方法

通过这种方式,您的代码流动得更好一些:

    private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
    {
        if (GetSelectedIndex(this.tabControlDbSwitch) == 0)
        {
            Console.WriteLine("Success!");
        }
    }

    private delegate int ReturnSelectedIndex(TabControl tb);
    private int GetSelectedIndex(TabControl tb)
    {
        if (tb.InvokeRequired)
        {
            return (int)tb.Invoke(new ReturnSelectedIndex(GetSelectedIndex), new Object[] { tb });
        }
        else
        {
            return tb.SelectedIndex;
        }
    }