C# winforms在当前选项卡忙于处理时在选项卡之间切换

C# winforms在当前选项卡忙于处理时在选项卡之间切换,c#,.net,winforms,multithreading,C#,.net,Winforms,Multithreading,我的winform(c#)具有多个选项卡,当前的焦点选项卡正忙于执行冗长的异步操作,并在“该选项卡中”嵌入progressbasr,显示进度。我想让用户能够导航到其他选项卡并执行其他任务,以防他/她不想等待。那么,我如何以简单而健壮的方式做到这一点呢 简而言之,这是一篇冗长的作品: foreach (DataRow _dr in _allDt.Rows) { //check if machine is online out of 100 machines list using async

我的winform(c#)具有多个选项卡,当前的焦点选项卡正忙于执行冗长的异步操作,并在“该选项卡中”嵌入progressbasr,显示进度。我想让用户能够导航到其他选项卡并执行其他任务,以防他/她不想等待。那么,我如何以简单而健壮的方式做到这一点呢

简而言之,这是一篇冗长的作品:

foreach (DataRow _dr in _allDt.Rows)
{
   //check if machine is online out of 100 machines list using async approach
        if (_connectionUtil.ConnectionIsOn(_dr["ipAddress"].ToString()))
            _onMachineAl.Add(_machineInfo);
    _progressBar.PerformStep();

 }
我必须用线吗?!还是更简单的方法?请提供代码段或有用的源代码

编辑:


谢谢,

您需要在单独的线程或后台工作程序中运行“长时间”操作。在这种情况下,UI将是免费的,用户可以继续使用应用程序。但不要忘记在操作完成时通知用户

以下是示例:

new System.Threading.Thread(new System.Threading.ThreadStart(delegate() 
    {
        foreach (DataRow _dr in _allDt.Rows)
        {
            //check if machine is online out of 100 machines list using async approach
            if (_connectionUtil.ConnectionIsOn(_dr["ipAddress"].ToString()))
                _onMachineAl.Add(_machineInfo);

            this._progressBar.Invoke(new MethodInvoker(delegate() // Invoke you need for accessing the UI thread and controls
            { 
                _progressBar.PerformStep();
            }));

        }
    })).Start();

如果您已经在异步执行任务,那么用户应该已经能够在选项卡之间切换,因为异步操作不会阻塞UI线程

如果您没有真正异步地执行任务,那么用户将无法执行很多操作,因为您正在阻塞UI线程

话虽如此,我怀疑你是在第二个阵营,所以类似这样的东西应该能帮助你开始行动:

var mi = new MethodInvoker(() =>
{
    foreach(dataRow _dr in _allDt.Rows)
    {
        if(_connectionUtil.ConnectionIsOn(_dr["ipAddress"].ToString()))
            _onMachineAl.Add(_machineInfo);
        this._progressBar.Invoke(() => { _progressBar.PerformStep(); });
    }
});
mi.BeginInvoke(null, null);

我真的不明白这个问题。。。。。?如果你已经在异步做事情,你不是已经在使用线程了吗?异步不会发生,因为你能提供更多信息吗?请检查我关于异步的编辑@jadook——仅仅因为您在TcpClient上使用异步方法,并不意味着您的循环是异步的。除此之外,似乎您正在使用异步方法,然后阻塞直到返回,因此您的
ConnectionIsOn()
方法可以返回true/false。@jadook,一旦阻塞,任何异步操作都会被浪费(在UI响应方面)。如果您实现了我的解决方案,那么您编写连接的方式将起作用。我不理解调用部分,为什么它链接到progressBar!PB是同一忙选项卡的一部分。你能再解释一下吗。thanksi在这个链接中找到了关于调用的答案:因为您处于不同的线程中,所以需要与UI线程通信。Invoke:在拥有控件底层窗口句柄的线程上执行指定的委托。我测试了您的代码,可以在选项卡之间切换,但在操作完成后,我无法在UI中看到结果。在实际代码中,在mi.BeginInvoke之后,我得到了更多的行。我应该如何处理该代码?资源呢!mi工作完成后是否自动销毁?还有最后一个问题:操作完成后如何显示msgBox。我需要做一些特别的事情还是仅仅用普通的方式。在beginInvoke()之后或之前放在哪里?您需要定义一个回调方法,并在
mi.beginInvoke()
调用中提供它。
var mi = new MethodInvoker(() =>
{
    foreach(dataRow _dr in _allDt.Rows)
    {
        if(_connectionUtil.ConnectionIsOn(_dr["ipAddress"].ToString()))
            _onMachineAl.Add(_machineInfo);
        this._progressBar.Invoke(() => { _progressBar.PerformStep(); });
    }
});
mi.BeginInvoke(null, null);