C# - 如何使用自定义代码与后台工作程序一起工作-Run,Pause,Stop?

时间:2013-08-01 07:02:20

标签: c# backgroundworker

我正在与后台工作者合作,但我既不能同步我的进度条也无法停止或中止该过程。

在我的dowork函数中

void bw_DoWork(object sender, DoWorkEventArgs e)
{
    if(bw.CancellationPending==true)
    {
        e.cancel=true;
        return;
    }
    else
    {
        e.Result = abc();
    }
}
int abc()
{
    //my work
    Count++;
    return count;
}

void bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
    if(bw.CancellationPending==true)
    {
        button17.Visibility = Visibility.Visible;
        label1.Content = "Aborted";
    }
    button17.Visibility = Visibility.Visible;
    label1.Content = "Completed";
}
private void Cancel_Click(object sender, RoutedEventArgs e)
{
    if(bw.IsBusy)
    {
        bw.CancelAsync();
    }
}

现在我想知道如何同步进度条以及如何退出进程?

3 个答案:

答案 0 :(得分:1)

您是否设置了BackgroundWorker.WorkerReportsProgress&&您的实例上的BackgroundWorker.WorkerSupportsCancellation属性为true

e.g。

var myBackgroundWorker = new BackgroundWorker();
myBackgroundWorker.WorkerReportsProgress = true;
myBackgroundWorker.WorkerSupportsCancellation = true;
//the rest of the init

如果您想报告进度,则需要在DoWork内调用BackgroundWorker.ReportProgress()方法。

答案 1 :(得分:0)

这是一个垃圾和微不足道的答案,但给任务并行库一个旋转。 http://msdn.microsoft.com/en-us/library/dd537608.aspx

此库将线程封装为离散的Task对象。它支持取消。

请注意,在工作线程中,工作程序代码本身必须支持暂停和取消操作,方法是轮询暂停/取消标记和令牌。单独使用线程无法安全地实现这些操作。

使用

是一种更好的模式

至于您的问题,需要2个标志才能支持您的操作。在工作代码期间,您需要定期检查它们。

bool pause = false;
bool cancel = false;
void DoWork()
{
    try
    {
        ...
        //periodically check the flags
        if(cancel) return;
        while(paused){}; //spin on pause
        ...
    }
    finally
    {
        //cleanup operation
    }
}

Alastair Pitts的回答说明了后台工作者如何支持这些功能。 MSDN也是如此;)http://msdn.microsoft.com/en-us/library/cc221403%28v=vs.95%29.aspx

答案 2 :(得分:0)

(您可能需要查看this其他SO问题/答案,了解有关新async设施的详细信息!它极大地提高了开展此类操作的生活质量!)

BackgroundWorker是基于事件的,基本用法如下(该链接提供了许多有用的其他详细信息):

var worker = new BackgroundWorker();

// The following two props must be true:
// #1: The worker will be enabled to signal its progress
worker.WorkerReportsProgress = true;
// #2: The worker will accept cancellation
worker.WorkerSupportsCancellation = true;

// Now the events:

worker.DoWork += (s,e) => 
{         
    int i = 0; // This goes from 0 to 100
    // Do code, update 'i'
    worker.ReportProgress(i); 

    worker.CancelAsync();     //... to cancel the worker if needed

    // WARNING: This code *cannot* interact with the UI because
    // it's running in a different thread
};

worker.ProgressChanged += (s,e)=> 
{ 
// This is executed when you call ReportProgress() from DoWork() handler
// IMPORTANT: All UI interaction **must** happen here    

// e.ProgressPercentage gives you the value of the parameter you passed to
// ReportProgress() (this mechanism is a perfect fit for a progress bar!)
};

worker.RunWorkerCompleted+= (s,e) => 
{
    // code here runs when DoWork() is done, is canceled or throws.
    // To check what happened, the link provides this sample code:
    if (e.Cancelled == true)
    {
        // Cancelled!
    }
    else if (e.Error != null)
    {
        // Exception !
    }
    else
    {
        // Work completed!
    }
};

worker.RunWorkerAsync();

重要的是要知道(从上面的链接中提取):

  

您必须小心不要操作DoWork事件处理程序中的任何用户界面对象。而是通过ProgressChanged和RunWorkerCompleted事件与用户界面进行通信。

更新此处的Lambda用于保持代码紧凑。显然,您可以使用“普通”处理程序或其他任何将代码附加到您喜欢/想要/需要的事件的方法。