0

I have code like below and i am facing UI Hung issue, there is no direct way to reproduce it. its occurring randomly 1 out 10 times. I am not able to identify what is causing issue.

I have below button click code which will show a child window:-

private void processCart_Click(object sender, RoutedEventArgs e)
{
    // processcart is Child Window Like Dialog To Open on Top Of Main Window
    processcart = new ProcessCart();

    processcart.Closed += ProcessCart_OnClosed;

    // Disable Parent Window 
    this.Dispatcher.Invoke(new Action(() =>
    {
        try
        {
            this.IsEnabled = false;
        }
        catch (Exception ex)
        { }
    }));

    processcart.Owner = Window.GetWindow(this);

    // Openning Child Window
    processcart.Show();
}

private void ProcessCart_OnClosed(object sender, EventArgs e)
{
    // On Child Window Close Doing some UI Update on Main Window
    totalChangeAmount.Dispatcher.Invoke(new Action(() =>
    {
        try
        {
            totalChangeAmount.Text = XFuelMath.roundingTwo(cart.ChangeTotal) + "";
        }
        catch
        { }
    }));

    // Starting Background Worker Thread for Database operation.
    if (!bgwTransaction.IsBusy)
    {
        bgwTransaction.RunWorkerAsync(cart);
    }
}

private void bgwTransaction_DoWork(object sender, DoWorkEventArgs e)
{
    // Doing some database operation but no UI Operation 

    // I dont know if i can call task inside background worker. 
    Task.Run(() => DeleteCurrentTicketDataFromDB(dataList, false)); 

    // Calling another background worker inside it 
    if (!bgwPrintRecipt.IsBusy)
    {
        bgwPrintRecipt.RunWorkerAsync();
    }
}

private void bgwPrintRecipt_DoWork(object sender, DoWorkEventArgs e)
{
    // Sending Data to printer 
}

private void bgwPrintRecipt_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
    // No Ui Operation Here 
}

private void bgwTransaction_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
    // Some UI Operation 
    totalSurcharge.Dispatcher.Invoke(() =>
    {
        totalSurcharge.Text = "0";
    });

    saleNumber.Dispatcher.Invoke(() => { });

    saleDataGrid.Dispatcher.Invoke(new Action(() =>
    {
        try
        {
            saleDataGrid.ItemsSource = currentSharedTicketCollection;
            saleDataGrid.Items.Refresh();

            if (isautoscroll && item!=null)
            {
                saleDataGrid.ScrollIntoView(item, saleDataGrid.Columns[0]);
                saleDataGrid.SelectedItem = item;
            }
        }
    }));

    // Enable the parent window Again 
    this.Dispatcher.Invoke(new Action(() =>
    {
        try
        {
            this.IsEnabled = true;
        }
        catch (Exception ex)
        { }
    }));
}

I am not sure if i am calling BackgroundWorker inside do DoWork and RunWorkerCompleted. Please guide me what i need to change in this code?

3
  • I'd start by getting rid of all the empty catch blocks Commented Oct 12, 2016 at 20:45
  • i have some logging code in catch block so i have removed it while posting. to make code shorter. Commented Oct 12, 2016 at 20:47
  • Mixing BackgroundWorker and Task.Run is just going to cause headaches, choose one or the other. Commented Oct 12, 2016 at 21:59

1 Answer 1

1

You should remove the Dispatcher call in your processCart_Click handler this will execute in the same UI thread and is not necessary at all unless you have several WPF windows in different threads created.

Besides that you should attach a debugger to the hung process and see where it hangs. If you have no debugger installed on the machine where it is executed you can right click in Task Manager and create a dump file. That file can be loaded into Visual Studio.

If your application is a 32 bit application executing on Windows x64 you need to close task manager and start the one from C:\Windows\SysWOW64\Taskmgr.exe to take a 32 bit dump on 64 bit Windows. If you do not do this you cannot load it into VS with managed call stacks.

Sign up to request clarification or add additional context in comments.

9 Comments

So is it right to use Dispatcher in RunWorkerCompleted? Or i dont need it there as well
If your worker is running on a different thread then you need the dispatcher calls to call into the UI threads. If you remove them you will get exceptions telling you that you did try to access a control from a different thread than it was created in.
i have given exe file to user and i did include pdb file for debug symbol. do i need to include this file with exe to get dump file generated with task manager and check the hung issue.
when child window close and ProcessCart_OnClosed get called as event handler in parent window, will that be part of another UI thread or same UI thread? do i need to focus on this method to take care of UI things?
No you do not need anything except the .dmp file from the user machine where it hangs. You can use also a different dump tool like the command line tool procdump.exe from SysInternals which will create always a dump of the right bitness. procdump -ma YourExe.exe
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.