【问题标题】:threads with BackgroudWorker, waits a long time . How can i avoid thisBackgroundWorker 的线程,等待很长时间。我怎样才能避免这种情况
【发布时间】:2016-08-31 06:54:22
【问题描述】:

我正在使用带有BackgroundWorker的线程,应用程序等待很长时间来获取50000条记录,它使其他操作等待该线程完成。使用辅助线程时如何避免等待过程。

private void btnExrtPDF_Click(object sender, RoutedEventArgs e)
{
    if (DetailsOrSummary == "Details")
        isDetails = true;

    Dispatcher.BeginInvoke(DispatcherPriority.Input, new ThreadStart(() =>
    {
        try
        {
            DetailReportFCBuySell = AlyexWCFService.DL.DLTTIn.FCBuySELL(
                transactionName, isDetails,
                Convert.ToDateTime(dateEdtStartDate.EditValue).Date,
                Convert.ToDateTime(dtpEditEndDate.EditValue).Date,
                Customerid, ProductID, branchID,
                NoOfRecords, PageIndex - 1, isBuy);

            worker.RunWorkerAsync();
        }
        catch
        {            
            object obj = new object(); 
        }
    }));
}

private void worker_DoWork(object sender, DoWorkEventArgs e)
{        
    Dispatcher.Invoke(new Action(() =>
    {
        System.Data.DataTable batchFCSB = new System.Data.DataTable();
        int row = 0;

        if (DetailReportFCBuySell.FirstOrDefault().TotalRecords > toFetchRecords)
        {
            long RecordsIcrease = 1000;
            batchFCSB = DetailReportFCBuySell.ToDataTable();
            //Collection.Add(row, batchFCSB);
            row = 1;
            PageIndex++;

            for (long k = toFetchRecords; k < DetailReportFCBuySell.FirstOrDefault().TotalRecords; k = +toFetchRecords)
            {
                new AlxServiceClient().Using(channel =>
                {
                    ObservableCollection<DLReports.FCBuySellDetail> temp
                        = AlyexWCFService.DL.DLTTIn.FCBuySELL(
                            transactionName, isDetails,
                            Convert.ToDateTime(dateEdtStartDate.EditValue).Date,
                            Convert.ToDateTime(dtpEditEndDate.EditValue).Date,
                            Customerid, ProductID, branchID, NoOfRecords, PageIndex - 1, isBuy);

                    DetailReportFCBuySell = DetailReportFCBuySell.Union(temp).ToObservableCollection();

                    row++;
                    PageIndex++;

                });
                toFetchRecords = toFetchRecords + RecordsIcrease;
            }
        }
    }), DispatcherPriority.ContextIdle);
}

【问题讨论】:

  • 只要确保更新 UI 组件和操作 observable 集合是在 UI 线程上完成的。目前,您正在 UI 线程上执行所有操作。
  • s 已经是我解决的问题了,感谢您对我的帮助。

标签: c# multithreading c#-4.0 backgroundworker


【解决方案1】:

您的代码完全错误。您不应该对Dispatcher.BeginInvoke()Dispatcher.Invoke() 进行任何调用。对BeginInvoke() 的调用毫无意义,没有任何用处,而后者导致所有工作实际上都在 UI 线程中完成,而不是在它所属的后台工作线程中完成。

您可以使用更现代的方法来代替BackgroundWorker,例如await Task.Run(...)。如果没有一个好的Minimal, Complete, and Verifiable code example,就不可能提出更具体的建议。但正如您现在发布的代码一样,如果您只是删除对Dispatcher 方法的所有调用并直接执行调用的代码,它应该可以按预期工作。

【讨论】:

  • 如果我删除了调度程序的所有调用(它显示“调用线程无法访问此对象,因为不同的线程拥有它。”)。 (还有一件事是我第一次在我的应用程序中使用 backgroundworker 和线程。所以从 stackOverflow 显示的示例中我做了很多,先生)
  • 如果没有好的minimal reproducible example,我无法分辨什么是 UI 对象,什么不是,因此无法提供比上述更具体的建议。确实,当您访问 UI 对象时,您必须使用 Dispatcher.Invoke() 或类似名称才能这样做。但是剩下的代码需要在后台线程中操作;将 整个 任务包装在对 Dispatcher.Invoke() 的调用中是不正确的,并且完全否定了使用 BackgroundWorker 的意义。
  • 你在这里问的问题是关于为什么你的BackgroundWorker 运行会阻塞 UI 线程,这个答案解决了这个问题。如果在解决该问题后,您仍然无法弄清楚如何正确更新 UI 对象,请发布一个新问题,这一次请确保您包含一个良好的 minimal reproducible example 以可靠地重现该问题。
【解决方案2】:

这就是您可以使用后台工作人员的方式。

在 WinForm 中添加 2 个按钮。

第一个 btnStartWorker 触发后台工作者。

当 btnStartWorker 被禁用并且后台 Worker 正在运行时,仍然可以单击 btnOther。

public partial class Form1 : Form
{
    private delegate void ReenableDelegate();

    public Form1()
    {
        InitializeComponent();
    }

    private BackgroundWorker worker;
    private void btnStartWorker_Click(object sender, EventArgs e)
    {
        btnStartWorker.Enabled = false;

        worker = new BackgroundWorker();
        worker.DoWork += Worker_DoWork;
        worker.RunWorkerCompleted += Worker_RunWorkerCompleted;
        worker.RunWorkerAsync();
    }

    private void Worker_DoWork(object sender, DoWorkEventArgs e)
    {

        Thread.Sleep(5000); // simulate long running operation here
    }

    private void Worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {
        this.Invoke(new ReenableDelegate(Enable));
    }

    private void Enable()
    {
        btnStartWorker.Enabled = true;
    }

    private void btnOther_Click(object sender, EventArgs e)
    {
        MessageBox.Show("Doing other stuff");
    }
}

【讨论】:

  • 不只有一个任务,这个方法我试过但是,UI 正在等待一段时间
  • 当你说等待时,你的意思是阻塞吗?
  • s,直到这个线程完成后,UI 才会工作。我需要在这个线程并行工作时工作 UI
猜你喜欢
  • 1970-01-01
  • 2013-09-14
  • 1970-01-01
  • 1970-01-01
  • 2015-08-10
  • 2013-09-29
  • 1970-01-01
  • 1970-01-01
  • 2011-01-27
相关资源
最近更新 更多