后台工作人员不更新 UI 并进入无限循环
Background worker doesn't update the UI and goes into an infinite loop
我收到了来自固件的回电。当我收到那个回电时,我想用适当的状态更新我的 UI。所以我 属性 更改了每次回调引发的事件,我正在后台线程中订阅该事件。
请在DoWork
中查看类似的while(!WorkDone
)。我正在阻止调用,因为我希望后台线程保留在 DoWork 中直到更新完成(我可以使用 ManualResetEvent
吗?)。问题是,即使我在 PropertyChanged
中将 WorkDone
设置为 true,它也永远不会被设置,并且我用来更新 UI 的 CurrentStatus 永远不会更新,并且程序会进入无限循环。请帮忙。
private void StartCurrentRun(bool obj)
{
this.worker = new BackgroundWorker();
this.worker.WorkerReportsProgress = true;
this.worker.WorkerSupportsCancellation = true;
StartTimer();
PropertyCallBackChangedInstance.PropertyChanged -= PropertyCallBackChangedInstance_PropertyChanged;
WhenCancelledBlurVolumesGrid = false;
OriginalTime = SelectedVolumeEstimatedTime();
this.worker.DoWork += this.DoWork;
this.worker.ProgressChanged += this.ProgressChanged;
this.worker.RunWorkerCompleted += Worker_RunWorkerCompleted;
IsLiveProgress = true;
this.worker.RunWorkerAsync();
}
private void DoWork(object sender, DoWorkEventArgs e)
{
try
{
CreateEventLogs.WriteToEventLog(string.Format("Run with Assay:{0} Volume{1} has been started", SelectedAssay, SelectedVolume), LogInformationType.Info);
var instance = ConnectToInstrument.InstrumentConnectionInstance;
instance.InitalizeRun(PopulateRespectiveVolumes());
PropertyCallBackChangedInstance.PropertyChanged += PropertyCallBackChangedInstance_PropertyChanged;
while (!WorkDone)
{
continue;
}
}
catch (Exception ex)
{
CreateEventLogs.WriteToEventLog(string.Format("{0} - {1}", "Error occured during Run", ex.Message), LogInformationType.Error);
}
}
private void PropertyCallBackChangedInstance_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
//bool stepDone = false;
if (e.PropertyName == "RunStepStatusName")
{
var value = sender as InstrumentCallBackProperties;
Dispatcher.CurrentDispatcher.BeginInvoke((Action)(() => {
CurrentStatus = value.RunStepStatusName;
if (value.RunStepStatusName == "Step5")
{
WorkDone = true;
}
}));
//stepDone = true;
}
}
private void ProgressChanged(object sender, ProgressChangedEventArgs e)
{
this.ProgressValue = e.ProgressPercentage;
}
这是 InitailizeRun 方法,当我调用它时我收到回调
public async void InitalizeRun(VolumeInfo volumeInfo)
{
AssayInfo AssayInfo = new AssayInfo();
AssayInfo.IVolume = volumeInfo;
CartridgeStepStatus StepStatus = new CartridgeStepStatus();
StepStatus.Data = AssayInfo;
await Task.Run(() => _instrument.ProcessCartridge(StepStatus));
}
这里是我收到的回电 我正在更新 属性
public void ProcessCartidge<T>(T data)
{
InstrumentCallBackPropertiesInstance.RunStepStatusName = data.ToString();
}
您可以将 BackgroundWorker
替换为 Task.Run
,因为它不适用于 async
和 await
。
Task.Run
启动一个后台线程,并且应该包含需要在单独线程上 运行 的代码。如果你想报告进度,你应该使用 IProgress 参数。
这个例子应该能让你朝着正确的方向前进。您可以在此基础上构建您的最终解决方案。
protected override async void OnLoadAsync( EventArgs e )
{
base.OnLoad( e );
try
{
IsLiveProgress = true;
await StartCurrentRunAsync( true );
}
catch ( Exception ex )
{
CreateEventLogs.WriteToEventLog( string.Format( "{0} - {1}" , "Error occured during Run" , ex.Message ) , LogInformationType.Error );
}
finally
{
IsLiveProgress = false;
}
}
private Task StartCurrentRunAsync( bool obj )
{
StartTimer();
PropertyCallBackChangedInstance.PropertyChanged -= PropertyCallBackChangedInstance_PropertyChanged;
WhenCancelledBlurVolumesGrid = false;
OriginalTime = SelectedVolumeEstimatedTime();
return Task.Run( () =>
{
CreateEventLogs.WriteToEventLog( string.Format( "Run with Assay:{0} Volume{1} has been started" , SelectedAssay , SelectedVolume ) ,
LogInformationType.Info );
var instance = ConnectToInstrument.InstrumentConnectionInstance;
return instance.InitalizeRun( PopulateRespectiveVolumes() );
} );
}
private void PropertyCallBackChangedInstance_PropertyChanged( object sender , PropertyChangedEventArgs e )
{
//bool stepDone = false;
if ( e.PropertyName == "RunStepStatusName" )
{
var value = sender as InstrumentCallBackProperties;
Dispatcher.CurrentDispatcher.BeginInvoke( ( Action ) ( () =>
{
CurrentStatus = value.RunStepStatusName;
if ( value.RunStepStatusName == "Step5" )
{
WorkDone = true;
}
} ) );
//stepDone = true;
}
}
我收到了来自固件的回电。当我收到那个回电时,我想用适当的状态更新我的 UI。所以我 属性 更改了每次回调引发的事件,我正在后台线程中订阅该事件。
请在DoWork
中查看类似的while(!WorkDone
)。我正在阻止调用,因为我希望后台线程保留在 DoWork 中直到更新完成(我可以使用 ManualResetEvent
吗?)。问题是,即使我在 PropertyChanged
中将 WorkDone
设置为 true,它也永远不会被设置,并且我用来更新 UI 的 CurrentStatus 永远不会更新,并且程序会进入无限循环。请帮忙。
private void StartCurrentRun(bool obj)
{
this.worker = new BackgroundWorker();
this.worker.WorkerReportsProgress = true;
this.worker.WorkerSupportsCancellation = true;
StartTimer();
PropertyCallBackChangedInstance.PropertyChanged -= PropertyCallBackChangedInstance_PropertyChanged;
WhenCancelledBlurVolumesGrid = false;
OriginalTime = SelectedVolumeEstimatedTime();
this.worker.DoWork += this.DoWork;
this.worker.ProgressChanged += this.ProgressChanged;
this.worker.RunWorkerCompleted += Worker_RunWorkerCompleted;
IsLiveProgress = true;
this.worker.RunWorkerAsync();
}
private void DoWork(object sender, DoWorkEventArgs e)
{
try
{
CreateEventLogs.WriteToEventLog(string.Format("Run with Assay:{0} Volume{1} has been started", SelectedAssay, SelectedVolume), LogInformationType.Info);
var instance = ConnectToInstrument.InstrumentConnectionInstance;
instance.InitalizeRun(PopulateRespectiveVolumes());
PropertyCallBackChangedInstance.PropertyChanged += PropertyCallBackChangedInstance_PropertyChanged;
while (!WorkDone)
{
continue;
}
}
catch (Exception ex)
{
CreateEventLogs.WriteToEventLog(string.Format("{0} - {1}", "Error occured during Run", ex.Message), LogInformationType.Error);
}
}
private void PropertyCallBackChangedInstance_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
//bool stepDone = false;
if (e.PropertyName == "RunStepStatusName")
{
var value = sender as InstrumentCallBackProperties;
Dispatcher.CurrentDispatcher.BeginInvoke((Action)(() => {
CurrentStatus = value.RunStepStatusName;
if (value.RunStepStatusName == "Step5")
{
WorkDone = true;
}
}));
//stepDone = true;
}
}
private void ProgressChanged(object sender, ProgressChangedEventArgs e)
{
this.ProgressValue = e.ProgressPercentage;
}
这是 InitailizeRun 方法,当我调用它时我收到回调
public async void InitalizeRun(VolumeInfo volumeInfo)
{
AssayInfo AssayInfo = new AssayInfo();
AssayInfo.IVolume = volumeInfo;
CartridgeStepStatus StepStatus = new CartridgeStepStatus();
StepStatus.Data = AssayInfo;
await Task.Run(() => _instrument.ProcessCartridge(StepStatus));
}
这里是我收到的回电 我正在更新 属性
public void ProcessCartidge<T>(T data)
{
InstrumentCallBackPropertiesInstance.RunStepStatusName = data.ToString();
}
您可以将 BackgroundWorker
替换为 Task.Run
,因为它不适用于 async
和 await
。
Task.Run
启动一个后台线程,并且应该包含需要在单独线程上 运行 的代码。如果你想报告进度,你应该使用 IProgress 参数。
这个例子应该能让你朝着正确的方向前进。您可以在此基础上构建您的最终解决方案。
protected override async void OnLoadAsync( EventArgs e )
{
base.OnLoad( e );
try
{
IsLiveProgress = true;
await StartCurrentRunAsync( true );
}
catch ( Exception ex )
{
CreateEventLogs.WriteToEventLog( string.Format( "{0} - {1}" , "Error occured during Run" , ex.Message ) , LogInformationType.Error );
}
finally
{
IsLiveProgress = false;
}
}
private Task StartCurrentRunAsync( bool obj )
{
StartTimer();
PropertyCallBackChangedInstance.PropertyChanged -= PropertyCallBackChangedInstance_PropertyChanged;
WhenCancelledBlurVolumesGrid = false;
OriginalTime = SelectedVolumeEstimatedTime();
return Task.Run( () =>
{
CreateEventLogs.WriteToEventLog( string.Format( "Run with Assay:{0} Volume{1} has been started" , SelectedAssay , SelectedVolume ) ,
LogInformationType.Info );
var instance = ConnectToInstrument.InstrumentConnectionInstance;
return instance.InitalizeRun( PopulateRespectiveVolumes() );
} );
}
private void PropertyCallBackChangedInstance_PropertyChanged( object sender , PropertyChangedEventArgs e )
{
//bool stepDone = false;
if ( e.PropertyName == "RunStepStatusName" )
{
var value = sender as InstrumentCallBackProperties;
Dispatcher.CurrentDispatcher.BeginInvoke( ( Action ) ( () =>
{
CurrentStatus = value.RunStepStatusName;
if ( value.RunStepStatusName == "Step5" )
{
WorkDone = true;
}
} ) );
//stepDone = true;
}
}