Nikhil ANS
Nikhil ANS

Reputation: 53

Background worker doesn't update the UI and goes into an infinite loop

I have call back that I am getting from a firmware. When I get that call back I want to update my UI with the appropriate status. So I have property changed event that gets raised for each call back and I am subscribing to the event in background thread.

Please look at the like while(!WorkDone) in DoWork. I am blocking the call since I want the background thread to stay in DoWork till the update completes (Sould I use ManualResetEvent?). Problem is even though I am setting the WorkDone to true in PropertyChanged it never gets set and the CurrentStatus with which I am updating the UI never updates and the program goes to an infinate loop. Please help.

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

Here is the InitailizeRun method when I call this I get call backs

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

And here is the call back whenever I get it I am updating the property

public void ProcessCartidge<T>(T data)
{
    InstrumentCallBackPropertiesInstance.RunStepStatusName = data.ToString();
}

Upvotes: 1

Views: 260

Answers (1)

Sievajet
Sievajet

Reputation: 3513

You can replace the BackgroundWorker with a Task.Run since it doesnt work well with async and await.

Task.Run starts a backgroundthread and should contain the code that needs to run on a seperate thread. If you want to report progress, you should use a IProgress parameter.

This example should get you in the right direction. You can build your final solution based on this.

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

Upvotes: 1

Related Questions