C#WPF UI冻结问题MultiThreading

时间:2016-10-12 20:39:38

标签: c# wpf backgroundworker

我有类似下面的代码,我正面临UI Hung问题,没有直接的方法来重现它。它随机发生1次10次。我无法确定导致问题的原因。

我有下面的按钮点击代码,它会显示一个子窗口: -

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

我不确定我是否在BackgroundWorkerDoWork内拨打RunWorkerCompleted。 请指导我在此代码中需要更改的内容?

1 个答案:

答案 0 :(得分:1)

您应该在processCart_Click处理程序中删除Dispatcher调用,这将在同一个UI线程中执行,除非您在创建的不同线程中有多个WPF窗口,否则根本不需要。

除此之外,您应该将调试器附加到挂起的进程并查看它挂起的位置。如果在执行它的计算机上没有安装调试器,则可以右键单击任务管理器并创建转储文件。该文件可以加载到Visual Studio中。

如果您的应用程序是在Windows x64上执行的32位应用程序,则需要关闭任务管理器并从C:\ Windows \ SysWOW64 \ Taskmgr.exe启动一个以在64位Windows上进行32位转储。如果不这样做,则无法将其加载到具有托管调用堆栈的VS中。