Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/wpf/13.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 背景工人不';t更新UI并进入无限循环_C#_Wpf_Multithreading_Backgroundworker - Fatal编程技术网

C# 背景工人不';t更新UI并进入无限循环

C# 背景工人不';t更新UI并进入无限循环,c#,wpf,multithreading,backgroundworker,C#,Wpf,Multithreading,Backgroundworker,我有回电话说我是从一个固件得到的。当我接到回电时,我想用适当的状态更新我的UI。因此,我已经更改了每次回调时引发的属性事件,并且我正在后台线程中订阅该事件 请在DoWork中查看类似的while(!WorkDone)。我正在阻止调用,因为我希望后台线程在更新完成之前保持工作状态(我应该使用ManualResetEvent?)。问题是,即使我在PropertyChanged中将WorkDone设置为true,它也永远不会被设置,并且我更新UI时使用的当前状态永远不会更新,并且程序进入内部循环。请帮

我有回电话说我是从一个固件得到的。当我接到回电时,我想用适当的状态更新我的UI。因此,我已经更改了每次回调时引发的属性事件,并且我正在后台线程中订阅该事件

请在
DoWork
中查看类似的while(
!WorkDone
)。我正在阻止调用,因为我希望后台线程在更新完成之前保持工作状态(我应该使用
ManualResetEvent
?)。问题是,即使我在
PropertyChanged
中将
WorkDone
设置为true,它也永远不会被设置,并且我更新UI时使用的当前状态永远不会更新,并且程序进入内部循环。请帮忙

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();
}
public void ProcessCartidge(T数据)
{
InstrumentCallbackPropertieInstance.RunStepStatusName=data.ToString();
}

您可以将
BackgroundWorker
替换为
任务。运行
,因为它与
异步
等待
不兼容

Task.Run
启动后台线程,并应包含需要在单独线程上运行的代码。如果要报告进度,应使用参数

这个例子应该能让你找到正确的方向。您可以在此基础上构建最终解决方案

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;
    }
}

这是C#吗?它没有这样标记。是的,很抱歉,我现在标记了“我应该使用ManualResetEvent吗?”-是的
volatile
WorkDone
变量前面应该有帮助。但是,
while(!WorkDone)
会毫无理由地给cpu带来压力。因此,在
WorkDone
变量上使用ManualResetEvent/TaskCompletionSource是正确的方法。感谢您的建议,Frank,我将更新它。