c# - 执行 ReportProgress 时,BackgroundWorker 或(Dispatcher)操作已完成

标签 c# mvvm backgroundworker wpf-4.0 dispatchertimer

我使用 DispatcherTimer 因为我需要每隔几分钟执行一次操作。在其中,我调用一个 BackgroundWorker 来完成我的工作,然后使用附加到计时器的调度程序来更新我的 UI。我认为我遇到的错误与计时器有关,但我不确定。是调度员完成还是后台工作人员完成?如何在 foreach 中执行 ReportProgress?

错误:

This operation has already had OperationCompleted called on it and further calls are illegal.

执行此操作时:

(sender as BackgroundWorker).ReportProgress((counterTotalSteps / 100) * counterOnStep);

这是简化的:

DispatcherTimer dispTimer = new DispatcherTimer();
Dispatcher dispatcher = dispTimer.Dispatcher;
dispTimer.Tick +=  delegate {dispTimer_Tick(dispatcher); };
dispTimer.Interval = new TimeSpan(0, 0, 45);
dispTimer.Start();

private void DoWork(object sender,Dispatcher dispatcher)
{
    int counterTotalSteps = PartialEmployees.Count();
    int counterOnStep = 1;

    dispatcher.BeginInvoke(new Action(() =>
    {                
        AllEmployees.Clear();
        //calling the ReportProgress here works
        foreach (var item in PartialEmployees)
        {
            counterOnStep ++;
            //part below throws the error
            (sender as BackgroundWorker).ReportProgress((counterTotalSteps / 100) *      counterOnStep); 
             AllEmployees.Add(item);                    
        }
        counterOnStep = 0;              
    }));           
}

编辑: 堆栈跟踪:

 at System.ComponentModel.AsyncOperation.VerifyNotCompleted()
   at System.ComponentModel.AsyncOperation.Post(SendOrPostCallback d, Object arg)
   at System.ComponentModel.BackgroundWorker.ReportProgress(Int32 percentProgress, Object userState)
   at System.ComponentModel.BackgroundWorker.ReportProgress(Int32 percentProgress)
   at testDispatcher.ViewModel.EmployeeListViewModel.<>c__DisplayClass7.<DoWork>b__6() in C:\Users\kozaj\Documents\Visual Studio 2010\Projects\testDispatcher\testDispatcher\ViewModel\EmployeeListViewModel.cs:line 91
   at System.Windows.Threading.ExceptionWrapper.InternalRealCall(Delegate callback, Object args, Int32 numArgs)
   at MS.Internal.Threading.ExceptionFilterHelper.TryCatchWhen(Object source, Delegate method, Object args, Int32 numArgs, Delegate catchHandler)
   at System.Windows.Threading.DispatcherOperation.InvokeImpl()
   at System.Windows.Threading.DispatcherOperation.InvokeInSecurityContext(Object state)
   at System.Threading.ExecutionContext.runTryCode(Object userData)
   at System.Runtime.CompilerServices.RuntimeHelpers.ExecuteCodeWithGuaranteedCleanup(TryCode code, CleanupCode backoutCode, Object userData)
   at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state)
   at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean ignoreSyncCtx)
   at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
   at System.Windows.Threading.DispatcherOperation.Invoke()
   at System.Windows.Threading.Dispatcher.ProcessQueue()
   at System.Windows.Threading.Dispatcher.WndProcHook(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam, Boolean& handled)
   at MS.Win32.HwndWrapper.WndProc(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam, Boolean& handled)
   at MS.Win32.HwndSubclass.DispatcherCallbackOperation(Object o)
   at System.Windows.Threading.ExceptionWrapper.InternalRealCall(Delegate callback, Object args, Int32 numArgs)
   at MS.Internal.Threading.ExceptionFilterHelper.TryCatchWhen(Object source, Delegate method, Object args, Int32 numArgs, Delegate catchHandler)
   at System.Windows.Threading.Dispatcher.InvokeImpl(DispatcherPriority priority, TimeSpan timeout, Delegate method, Object args, Int32 numArgs)
   at MS.Win32.HwndSubclass.SubclassWndProc(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam)
   at MS.Win32.UnsafeNativeMethods.DispatchMessage(MSG& msg)
   at System.Windows.Threading.Dispatcher.PushFrameImpl(DispatcherFrame frame)
   at System.Windows.Threading.Dispatcher.PushFrame(DispatcherFrame frame)
   at System.Windows.Threading.Dispatcher.Run()
   at System.Windows.Application.RunDispatcher(Object ignore)
   at System.Windows.Application.RunInternal(Window window)
   at System.Windows.Application.Run(Window window)
   at System.Windows.Application.Run()
   at testDispatcher.App.Main() in C:\Users\kozaj\Documents\Visual Studio 2010\Projects\testDispatcher\testDispatcher\obj\x86\Debug\App.g.cs:line 50
   at System.AppDomain._nExecuteAssembly(RuntimeAssembly assembly, String[] args)
   at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
   at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
   at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
   at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean ignoreSyncCtx)
   at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
   at System.Threading.ThreadHelper.ThreadStart()

最佳答案

事件顺序

  1. DoWork 被调用
  2. DoWork 放置“AllEmployees.Clear();”进入调度程序队列
  3. DoWork 完成
  4. 调度员看到“AllEmployees.Clear();”并开始处理该函数。

我建议仅在实际具有 UI 交互的步骤上使用dispatcher.Invoke(立即运行它)。

关于c# - 执行 ReportProgress 时,BackgroundWorker 或(Dispatcher)操作已完成,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4217777/

相关文章:

c# - 从 COM .dll 获取错误 '80070002'

c# - SQL 2000 的 NHibernate 变量限制

android - 如何在Android的MVVM架构中将 Action 从View发送到ViewModel

c# - 如何在 ViewModel 中设置从模型列表中获取和设置值的属性?

C# 后台 worker 问题

c# - 如何优化此 LINQ to EF/Sql 查询(多对多关系)?

c# - 使用 WiX DTF 获取组件代码

c# - 回调第二次不起作用

c# - 在 WPF 中,Windows 窗体中的 Suspend/ResumeLayout() 和 BackgroundWorker() 等同于什么

c# - 使用后台 worker 时如何正确处理表单关闭?