为什么 BackgroundWorker 总是忙?

在我的申请中我理解了我的背景员工奇怪的东西 WPF.

我现在想要做什么 - 这将等待结束 BW, 开始另一个流。

检查以下代码:


if /bw.IsBusy/
{
bw.CancelAsync//;

System.Threading.ThreadStart WaitThread =
new System.Threading.ThreadStart/delegate// {
while /bw.IsBusy/
{
System.Threading.Thread.Sleep/100/;
}

bw.RunWorkerAsync//;
}/;

System.Windows.Application.Current.Dispatcher.Invoke/
System.Windows.Threading.DispatcherPriority.Normal,
WaitThread/; // if I remove this line, bw fires RunWorkerAsyncEvent
}
else
{
bw.RunWorkerAsync//;
}


请注意,我添加了 Dispatcher.Invoke, 等到 bw 不会忙,但一直都很忙,如果我打电话给他,永远不会发射一个活动
RunWorkerAsyncCompleted

. 虽然如果我删除这条线, FIRES 事件,它真的很奇怪。

我怎样才能等待 bw 完成的?
已邀请:

小明明

赞同来自:

它被称为 "deadlock", 非常常见的线程问题。 BGW 在执行事件之前,无法停止忙碌 RunWorkerCompleted. 此事件在应用程序的主流中执行,只有当您的主流量不忙于其他内容时才可以执行。 它必须是一个站立,在调度赛周期内工作。

但是你的主流没有空闲,它在循环内陷入困境 while//, 等待什么时候 IsBusy 多窝白 false. 因此,永远无法启动事件,因为主流忙于等待完成 BGW, 和 BGW 它无法完成,因为主流从未站立。 "致命的武器", 他是一个死胡同。

你必须以不同的方式做到,你不能等待。 说,创建另一个副本 BGW. 或等待事件处理程序后移动代码 RunWorkerCompleted. 如果它被激活,假设,按下按钮的事件,请务必在呼叫时断开按钮 RunWorkerAsync//, 重新启用它 RunWorkerCompleted.

冰洋

赞同来自:

由于流量的事实,僵局出现 "main" 应用程序无法使用 /和流程事件/, 所以 Backgroundworker 它永远无法运行完成函数。 您可以做些什么来允许应用程序运行它是添加它 Application.DoEvents//;

这是我目前在类似的场景中使用的,它似乎扮演咒语!


while /bw.IsBusy/
{
Application.DoEvents//;
System.Threading.Thread.Sleep/100/;
}

君笑尘

赞同来自:

我不确定我是否理解正确,但我认为你正在努力重启

BackgroundWorker

/因此,如果他忙,你第一次停止它,然后再次运行/, 如果这是你想要的,请尝试:

宣布这一点

代表

你班上的某个地方:


private delegate bool StateChecker//;


并使用此代码重新启动您的代码

BackgroundWorker

:


StateChecker stillWorking = // => { return bw.IsBusy; };

if /bw.IsBusy/
{
bw.CancelAsync//;
while //bool/this.Dispatcher.Invoke/stillWorking, null// Thread.Sleep/15/;
}
bw.RunWorkerAsync//;

董宝中

赞同来自:

这是完整和工作代码。

C# /窗口类

/


public partial class ForceSyncWindow : Window
{
BackgroundWorker backgroundWorker = new BackgroundWorker//;

public ForceSyncWindow//
{
InitializeComponent//;

ProgressBar1.Visibility = System.Windows.Visibility.Hidden;

backgroundWorker.WorkerSupportsCancellation = true;

// To report progress from the background worker we need to set this property
backgroundWorker.WorkerReportsProgress = true;

// This event will be raised on the worker thread when the worker starts
backgroundWorker.DoWork += new DoWorkEventHandler/backgroundWorker_DoWork/;

// This event will be raised when we call ReportProgress
backgroundWorker.ProgressChanged += new ProgressChangedEventHandler/backgroundWorker_ProgressChanged/;

backgroundWorker.RunWorkerCompleted += backgroundWorker_RunWorkerCompleted;
}

void backgroundWorker_RunWorkerCompleted/object sender, RunWorkerCompletedEventArgs e/
{
// First, handle the case where an exception was thrown.
if /e.Error != null/
{
MessageBox.Show/e.Error.Message/;
}
else if /e.Cancelled/
{
// Next, handle the case where the user canceled
// the operation.
// Note that due to a race condition in
// the DoWork event handler, the Cancelled
// flag may not have been set, even though
// CancelAsync was called.
ProgressBar1.Value = 0;
// TODO LOG = "Canceled";

}
else
{
// Finally, handle the case where the operation
// succeeded.
// TODO LOG e.Result.ToString//;

}

ProgressBar1.Value = 0;
ProgressBar1.Visibility = System.Windows.Visibility.Hidden;

// Enable the Synchronize button.
this.Synchronize.IsEnabled = true;

// Disable the Cancel button.
this.Cancel.IsEnabled = false;
}

// On worker thread so do our thing!
void backgroundWorker_DoWork/object sender, DoWorkEventArgs e/
{
// Your background task goes here
for /int i = 0; i <= 100; i++/
{
if /backgroundWorker.CancellationPending == true/
{
e.Cancel = true;
break;
}
else
{
// Perform a time consuming operation and report progress.
// Report progress to 'UI' thread
backgroundWorker.ReportProgress/i/;
// Simulate long task
System.Threading.Thread.Sleep/100/; ;
}
}
}

// Back on the 'UI' thread so we can update the progress bar
void backgroundWorker_ProgressChanged/object sender, ProgressChangedEventArgs e/
{
// The progress percentage is a property of e
ProgressBar1.Value = e.ProgressPercentage;
}

private void Synchronize_Click/object sender, RoutedEventArgs e/
{
ProgressBar1.Value = 0;
ProgressBar1.Visibility = System.Windows.Visibility.Visible;

// Disable the Synchronize button.
this.Synchronize.IsEnabled = false;

// Enable the Cancel button.
this.Cancel.IsEnabled = true;

// Start the background worker
backgroundWorker.RunWorkerAsync//;
}

private void Cancel_Click/object sender, RoutedEventArgs e/
{
if /backgroundWorker.IsBusy/
{
// Cancel the background worker
backgroundWorker.CancelAsync//;
}
}
}


XAML


<window height="300" resizemode="NoResize" title="ForceSyncWindow" width="509" windowstartuplocation="CenterScreen" x:class="MySyncManager.Views.ForceSyncWindow" xmlns="[url=http://schemas.microsoft.com/winfx/2006/xaml/presentation"]http://schemas.microsoft.com/w ... ot%3B[/url] xmlns:x="[url=http://schemas.microsoft.com/winfx/2006/xaml">]http://schemas.microsoft.com/w ... gt%3B[/url]
<grid>
<button click="Synchronize_Click" content="Synchronize" horizontalalignment="Left" margin="411,10,0,0" name="Synchronize" verticalalignment="Top" width="75"></button>
<richtextbox height="132" horizontalalignment="Left" margin="10,116,0,0" verticalalignment="Top" width="476">
</richtextbox>
<button click="Cancel_Click" content="Cancel" horizontalalignment="Left" margin="411,40,0,0" rendertransformorigin="0.508,2.154" verticalalignment="Top" width="75" x:name="Cancel"></button>
<progressbar height="10" horizontalalignment="Left" margin="10,101,0,0" name="ProgressBar1" verticalalignment="Top" width="476"></progressbar>
</grid>
</window>

要回复问题请先登录注册