【问题标题】:How can I abort/cancel the forwarded BackgroundWorker?如何中止/取消转发的 BackgroundWorker?
【发布时间】:2014-12-21 05:06:51
【问题描述】:

如您所见,here 有一个用于 ftp 传输的后台工作程序。
Franks 的回答显示了一个带有一些重写方法的新类,因此可以获得传输速度和它的百分比。

我想取消运行上传的后台工作程序,但我不知道如何。

实施

public UpAndDownloadForm(Job pJob)
    {
        InitializeComponent();
        this.job = pJob;
        bGroundWorker = new BackgroundWorker();
        bGroundWorker.WorkerReportsProgress = true;
        bGroundWorker.WorkerSupportsCancellation = true;

        bGroundWorker.DoWork += new DoWorkEventHandler(bGroundWorker_DoWork);
        bGroundWorker.ProgressChanged += new ProgressChangedEventHandler(bGroundWorker_ProgressChanged);
        bGroundWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bGroundWorker_RunWorkerCompleted);

        bGroundWorker.RunWorkerAsync(pJob);
    }

DoWork:

void bGroundWorker_DoWork(object sender, DoWorkEventArgs e)
    {
        streamWithTransferSpeedWorker = (BackgroundWorker)sender;
        Job job = (Job)e.Argument;
        string[] files = Directory.GetFiles(job.GetSourceFolder(), "*.*", SearchOption.AllDirectories);

        if (bGroundWorker.CancellationPending) //Falls der bGWorker abgebrochen wurde, beendet man diesen wohl einfach mit e.Cancel;
        {
            e.Cancel = true;
            return;
        }
        foreach (string file in files)
        {
            char[] temp = file.ToCharArray(); //Dateipfad in CharArray speichern
            Array.Reverse(temp); //Reihenfolge ändern (von hinten nach vorne)
            string fileReversed = new string(temp); //als string speichern
            int index = fileReversed.IndexOf(@"\"); //die Zeichenlänge des DateiNAMENs auslesen
            string fileOnlyName = file.Substring(file.Length - index, index); //nur den Dateinamen auslesen


            FtpWebRequest request = (FtpWebRequest)WebRequest.Create(job.GetDestinationFolder() + "\\" + fileOnlyName);
            request.Method = WebRequestMethods.Ftp.UploadFile;
            request.Credentials = new NetworkCredential(Manager._user, Manager._password);


            var response = (FtpWebResponse)request.GetResponse(); //WebResponse response = request.GetResponse(); 

            using (Stream source = File.OpenRead(file))
            {
                using (var destination = new StreamWithTransferSpeed(request.GetRequestStream(), streamWithTransferSpeedWorker, source.Length))//request.ContentLength))
                {
                    source.CopyTo(destination);
                }
            }

            Console.WriteLine("Upload File Complete, status {0}", response.StatusDescription);
            response.Close();
        }
    }

取消BackgroundWorker:

private void btnCancelLoad_Click(object sender, EventArgs e)
    {
        if (bGroundWorker.IsBusy)
        {
            bGroundWorker.CancelAsync();
        }
        if (streamWithTransferSpeedWorker.IsBusy)
        {
            streamWithTransferSpeedWorker.CancelAsync();
        }
    }


如您所见,我已经尝试了一些方法,但没有任何意义。
Button-Click-Event 后用于开始上传的 Backgroundworker-CancellationPending-Flag 为 true,但上传仍在运行。

我是不是误会了什么?
在写这个问题的过程中,我想过取消CopyTo-Method,但我什至不知道这是否有效或者这是否是问题/解决方案。
感谢帮助。


EDIT1:
在这里可以看到转发的BackgroundWorkerusing (var destination = new StreamWithTransferSpeed(request.GetRequestStream(), streamWithTransferSpeedWorker, source.Length))


EDIT2:
正如T MCKeown所说:bool实例
UploadForm.cs:
private void btnCancelLoad_Click(object sender, EventArgs e)
    {
        if (bGroundWorker.IsBusy)
        {
            bGroundWorker.CancelAsync();
            Manager._cancelBackgroundWorker = true;
        }
    }

还有我的部分:
StreamWithTransferSpeed.cs:

if (Manager._cancelBackgroundWorker)
{
    this.worker.CancelAsync(); //this is useless, because the Backgroundworker is still running
    Manager._cancelBackgroundWorker = false;
    innerStream.Close(); //this is dirty, but it works, after the Closing the backgroundworker is canceled
}

在这里您可以看到CancelAsync()。它在 Console.WriteLine("bGW direkt unter der exception abgebrochen");:
UploadForm.cs:

处执行
void bGroundWorker_DoWork(object sender, DoWorkEventArgs e)
    {
        BackgroundWorker worker = (BackgroundWorker)sender;
        Job job = (Job)e.Argument;
        string[] files = Directory.GetFiles(job.GetSourceFolder(), "*.*", SearchOption.AllDirectories);

        foreach (string file in files)
        {
            if (bGroundWorker.CancellationPending) //Falls der bGWorker abgebrochen wurde, beendet man diesen wohl einfach mit e.Cancel;
            {
                e.Cancel = true; //Sinnlos da es eh nicht funktioniert
                Console.WriteLine("bGW direkt unter foreach abgebrochen");
                return;
            }
            char[] temp = file.ToCharArray(); //Dateipfad in CharArray speichern
            Array.Reverse(temp); //Reihenfolge ändern (von hinten nach vorne)
            string fileReversed = new string(temp); //als string speichern
            int index = fileReversed.IndexOf(@"\"); //die Zeichenlänge des DateiNAMENs auslesen
            string fileOnlyName = file.Substring(file.Length - index, index); //nur den Dateinamen auslesen

            FtpWebRequest request = (FtpWebRequest)WebRequest.Create(job.GetDestinationFolder() + "\\" + fileOnlyName);
            request.Method = WebRequestMethods.Ftp.UploadFile;
            request.Credentials = new NetworkCredential(Manager._user, Manager._password);

            var response = (FtpWebResponse)request.GetResponse(); //WebResponse response = request.GetResponse(); 
            try
            {
                using (Stream source = File.OpenRead(file))
                {
                    using (var destination = new StreamWithTransferSpeed(request.GetRequestStream(), worker, source.Length))//request.ContentLength))
                    {
                        source.CopyTo(destination);
                    }
                }
            }
            catch (Exception ex)
            {
                if (ex.GetType() == typeof(ObjectDisposedException))
                {
                    Console.WriteLine("Upload canceled.");
                    if (bGroundWorker.CancellationPending) //Falls der bGWorker abgebrochen wurde, beendet man diesen wohl einfach mit e.Cancel;
                    {
                        e.Cancel = true; //Sinnlos da es eh nicht funktioniert
                        Console.WriteLine("bGW direkt unter der exception abgebrochen");
                        return;
                    }
                }                    
            }

            Console.WriteLine("Upload File Complete, status {0}", response.StatusDescription);
            response.Close();
        }
    }

【问题讨论】:

  • 您只在 DoWork 事件处理程序开始时测试 CancellationPending。在这一点上,它有 99.99% 的保证是 false。当你做昂贵的事情时,你必须检查它。在你的循环里面。如果您希望它具有响应性,也不能使用 CopyTo()。
  • 我同意@HansPassant,您应该在循环中实现数据传输,在传输每个数据块后检查CancellationPending 值。

标签: c# stream backgroundworker


【解决方案1】:

创建一个实例_cancel变量bool

private void btnCancelLoad_Click(object sender, EventArgs e)
{
  _cancel = true;
  ...
}

然后在这里查看:

foreach (string file in files)
    {
       if (_cancel ) return;

        char[] temp = file.ToCharArray(); //Dateipfad in CharArray speichern
        ...

在您可能想要检查取消的任何其他地方添加 if 语句。

对 EDIT2 的回应:

您将代码更改为:

foreach (string file in files)
    {
        if (bGroundWorker.CancellationPending) //Falls der bGWorker abgebrochen wurde, beendet man diesen wohl einfach mit e.Cancel;
        {
            e.Cancel = true; //Sinnlos da es eh nicht funktioniert
            Console.WriteLine("bGW direkt unter foreach abgebrochen");
            return;
        }

我曾建议你这样做:

foreach (string file in files)
    {
        if (Manager._cancelBackgroundWorker) //Falls der bGWorker abgebrochen wurde, beendet man diesen wohl einfach mit e.Cancel;
        {
            e.Cancel = true; //Sinnlos da es eh nicht funktioniert
            Console.WriteLine("bGW direkt unter foreach abgebrochen");
            return;
        }

您在单击取消时将此布尔值设置为 true 是吗?

【讨论】:

  • 也没有用。后台工作者仍在运行。 BackgroundWorker 仅在上传完成后才会取消。
  • 该代码已被删除。我有一个解决方案,但它不是很漂亮。我会在几分钟后将其发布到我的编辑中。
  • 当您单击取消时,该代码是完全执行还是被阻止?如果 bool 设置为 true,那么我看不出它不会退出的原因......我错过了什么?
  • 当我单击取消时,StreamWithTransferSpeed 中的写入方法已完全执行,尽管标志为真。我不知道这里发生了什么。
  • 是的,我将此布尔值设置为 true。我也改变了它,但我必须先修复另一个例外。我会告诉你它是否有效。你是对的,我忘了更改 if 子句。感谢优势..我认为它会起作用:)
【解决方案2】:

Cancel校验码放入Foreach循环

if (bGroundWorker.CancellationPending) //Falls der bGWorker abgebrochen wurde, beendet man diesen wohl einfach mit e.Cancel;
{
    e.Cancel = true;
    return;
}

【讨论】:

  • 这并没有真正起作用,但我不知道为什么。上传仍在运行。上传完成后,Backgroundworker 被取消。
猜你喜欢
  • 1970-01-01
  • 2012-03-27
  • 2023-03-23
  • 2015-01-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多