C#取消的背景工人的DoWork [英] C# cancelling DoWork of background worker

查看:108
本文介绍了C#取消的背景工人的DoWork的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

C#2008

我用下面的code登录到软电话。然而,登录陆侃是一个漫长的过程,因为有有被初始化,并作出检查很多事情,我只放了几个放在这里,因为它会在code长期张贴。

在code下面我检查,如果如果CancelAsync的CancellationPending被称为在我的取消按钮单击事件,每次做检查之前。它是否正确?此外,如果检查失败,我又拨打了CancelAsync和e.Cancel设置为true。

我想知道如果我的方法,我在这里使用的是用最好的方法。

非常感谢任何建议,

 私人无效bgwProcessLogin_DoWork(对象发件人,DoWorkEventArgs E)
    {
        / *
         *在试验执行以查看是否背景工人已
         * attemping继续登录后才被用户取消。
         *
         *取消后台工作的任何失败学尝试登录
         * /        //开始与取消是虚假,如果取消已设置为true重置此
        //在取消按钮。
        e.Cancel = FALSE;        NetworkingTest connection_test =新NetworkingTest();
        如果(!this.bgwProcessLogin.CancellationPending)
        {
            //检查局域网或无线连接
            如果(!connection_test.IsNetworkConnected())
            {
                //更新标签
                如果(this.lblRegistering.InvokeRequired)
                {
                    this.lblRegistering.Invoke(新UpdateRegisterLabelDelegate(UpdateRegisterLabel),无网络连接);
                }
                其他
                {
                    this.lblRegistering.Text =无网络连接;
                }
                //失败学尝试
                this.bgwProcessLogin.CancelAsync();
                e.Cancel =真;
                返回;
            }
            //报告目前的进展
            this.bgwProcessLogin.ReportProgress(0,网络连接);
        }
        其他
        {
            //用户取消
            e.Cancel =真;
            返回;
        }        //如果访问服务器可用的测试
        如果(!this.bgwProcessLogin.CancellationPending)
        {
            如果(!connection_test.IsSIPServerAvailable())
            {
                //更新标签
                如果(this.lblRegistering.InvokeRequired)
                {
                    this.lblRegistering.Invoke(新UpdateRegisterLabelDelegate(UpdateRegisterLabel),服务器不可用);
                }
                其他
                {
                    this.lblRegistering.Text =服务器不可用;
                }
                //失败学尝试
                this.bgwProcessLogin.CancelAsync();
                e.Cancel =真;
                返回;
            }
            //报告目前的进展
            this.bgwProcessLogin.ReportProgress(1,服务器可用);
        }
        其他
        {
            //用户取消
            e.Cancel =真;
            返回;
        }
        。
        。
        。
}
 私人无效bgwProcessLogin_RunWorkerCompleted(对象发件人,RunWorkerCompletedEventArgs E)
    {
        //检查错误
        如果(e.Error == NULL)
        {
            如果(e.Cancelled)
            {
                //用户取消登录或登录失败
            }
            其他
            {
                //登录成功完成
            }
        }
        其他
        {
            //有失败的显示错误
            this.statusDisplay1.CallStatus = e.Error.Message;
        }
    }
 私人无效bgwProcessLogin_ProgressChanged(对象发件人,ProgressChangedEventArgs E)
    {
        this.lblRegistering.Text = e.UserState.ToString();
    }私人无效btnCancel_Click(对象发件人,EventArgs的发送)
    {
        //取消过程记录
        this.bgwProcessLogin.CancelAsync();
        this.lblRegistering.Text =注销;
}


解决方案

有可能是只有一个问题:如果DoWork的事件处理程序的操作之一将持续很长一段时间。在这种情况下,你可以放弃你的挂起操作后,只有操作完成。如果DoWork的情况下,所有操作都可以在此情况下,用户持续很长时间(例如,不超过5秒),它的一切OK,但如果操作中的一个可以持续很长一段时间(5分钟,例如)有等到该操作完成。

如果DoWork的含有持久的操作,您可以使用类似AbortableBackgroundWorker。事情是这样的:

 公共类AbortableBackgroundWorker:BackgroundWorker的
{
    私人主题的WorkerThread;    保护覆盖无效OnDoWork(DoWorkEventArgs E)
    {
        的WorkerThread = Thread.CurrentThread;
        尝试
        {
            base.OnDoWork(E);
        }
        赶上(ThreadAbortException)
        {
            e.Cancel =真; //我们必须将取消属性设置为true!
            Thread.ResetAbort(); // prevents ThreadAbortException传播
        }
    }
    公共无效中止()
    {
        如果(的WorkerThread!= NULL)
        {
            workerThread.Abort();
            的WorkerThread = NULL;
        }
    }
}

在这种情况下,你可以真正中止等待的操作,但你也有一些限制(有关详细信息,关于中止托管线程和一些限制看到的水暖ThreadAbortException使用转子)的深处。

P.S。我跟奥利弗同意,你应该更多的有用的形式包装InvokeRequired。

C# 2008

I am using the code below to login to a softphone. However, the login progess is a long process as there are many things that have to be initialized and checks to be made, I have only put a few on here, as it would make the code to long to post.

In the code below I am checking if the CancellationPending if the CancelAsync has been called in my cancel button click event, before doing each check. Is this correct? Also if the check fails I also call the CancelAsync and set the e.Cancel to true.

I would like to know if my method I have used here is the best method to use.

Many thanks for any advice,

private void bgwProcessLogin_DoWork(object sender, DoWorkEventArgs e)
    {   
        /*
         * Perform at test to see if the background worker has been
         * cancelled by the user before attemping to continue to login.
         * 
         * Cancel background worker on any failed attemp to login
         */

        // Start with cancel being false as to reset this if cancel has been set to true
        // in the cancel button.
        e.Cancel = false;

        NetworkingTest connection_test = new NetworkingTest();
        if (!this.bgwProcessLogin.CancellationPending)
        { 
            // Check local LAN or Wireless connection               
            if (!connection_test.IsNetworkConnected())
            {
                // Update label
                if (this.lblRegistering.InvokeRequired)
                {
                    this.lblRegistering.Invoke(new UpdateRegisterLabelDelegate(UpdateRegisterLabel), "No network connection");
                }
                else
                {
                    this.lblRegistering.Text = "No network connection";
                }
                // Failed attemp
                this.bgwProcessLogin.CancelAsync();
                e.Cancel = true;
                return;
            }
            // Report current progress
            this.bgwProcessLogin.ReportProgress(0, "Network connected");
        }
        else
        {
            // User cancelled 
            e.Cancel = true;
            return;
        }

        // Test if access to Server is available
        if (!this.bgwProcessLogin.CancellationPending)
        {
            if (!connection_test.IsSIPServerAvailable())
            {
                // Update label
                if (this.lblRegistering.InvokeRequired)
                {
                    this.lblRegistering.Invoke(new UpdateRegisterLabelDelegate(UpdateRegisterLabel), "Server unavailable");
                }
                else
                {
                    this.lblRegistering.Text = "Server unavailable";
                }
                // Failed attemp
                this.bgwProcessLogin.CancelAsync();
                e.Cancel = true;
                return;
            }
            // Report current progress
            this.bgwProcessLogin.ReportProgress(1, "Server available");
        }
        else
        {
            // User cancelled 
            e.Cancel = true;
            return;
        }
        .
        .
        .
}


 private void bgwProcessLogin_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {   
        // Check for any errors
        if (e.Error == null)
        {
            if (e.Cancelled)
            {
                // User cancelled login or login failed                
            }
            else
            {
                // Login completed successfully                
            }
        }
        else
        {
            // Something failed display error
            this.statusDisplay1.CallStatus = e.Error.Message;
        }
    }


 private void bgwProcessLogin_ProgressChanged(object sender, ProgressChangedEventArgs e)
    {
        this.lblRegistering.Text = e.UserState.ToString();
    }

private void btnCancel_Click(object sender, EventArgs e)
    {
        // Cancel the logging in process
        this.bgwProcessLogin.CancelAsync();
        this.lblRegistering.Text = "Logged out";
}

解决方案

There is maybe only one problem: if one of the operation in DoWork event handler would last for a long time. In this case you could abort your pending operation ONLY after that operation finished. If all operations in DoWork event can't last very long (for instance, no more than 5 seconds), its all OK, but if one of the operations can last for long time (5 minutes, for instance) in this case user have to wait until this operation finished.

If DoWork contains long lasting operations you can use something like AbortableBackgroundWorker. Something like this:

public class AbortableBackgroundWorker : BackgroundWorker
{
    private Thread workerThread;

    protected override void OnDoWork(DoWorkEventArgs e)
    {
        workerThread = Thread.CurrentThread;
        try
        {
            base.OnDoWork(e);
        }
        catch (ThreadAbortException)
        {
            e.Cancel = true; //We must set Cancel property to true!
            Thread.ResetAbort(); //Prevents ThreadAbortException propagation
        }
    }


    public void Abort()
    {
        if (workerThread != null)
        {
            workerThread.Abort();
            workerThread = null;
        }
    }
}

In this case you can truly abort pending operations, but you also have some restrictions (for more information about aborting managed thread and some restrictions see Plumbing the Depths of the ThreadAbortException Using Rotor).

P.S. I agree with Oliver that you should wrap InvokeRequired in more usable form.

这篇关于C#取消的背景工人的DoWork的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆