2010-11-18 143 views
2

我使用DispatcherTimer,因为我需要每隔几分钟执行一次操作。在这个内部我打电话BackgroundWorker来完成我的工作,然后使用定时器上的调度器来更新我的UI。我在想我得到的错误与计时器有关,但我不确定。调度员完成了还是后台工作?我该如何做foreach中的ReportProgress?BackgroundWorker或(Dispatcher)操作在完成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() 
+0

什么是堆栈跟踪? – SLaks 2010-11-18 17:39:31

+1

为什么使用BackgroundWorker,但是在UI线程上执行所有工作? – SLaks 2010-11-18 17:41:03

+0

这只是示例代码,以查看在其他事情中实现它之前是否可以使其正常工作。你会在dipatcher外面移动哪一部分?这些列表也绑定到UI。 – LobalOrning 2010-11-18 17:55:51

回答

3

序列

  1. DoWork的被称为
  2. DoWork的把 “AllEmployees.Clear();”进入调度员队列
  3. DoWork完成
  4. 调度员看到“AllEmployees.Clear();”并开始处理该功能。

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

+0

使用.Invoke()效果很好。我正在做的是增加progressBar,但它似乎一次完成(直到100%)。当我在WorkerProgressChanged()上放置一个断点时,它在foreach调用它时不会被调用,而是在foreach之后调用它调用的次数 - 或者它看起来是这样。有什么建议么? – LobalOrning 2010-11-18 18:32:06

+0

'ReportProgress'在内部调用'BeginInvoke'来报告进度。它发布的消息只在UI线程空闲时才处理,完成后。 – SLaks 2010-11-18 19:18:13

1

由于您的工作是在UI线程上完成的,因此根本不应该使用BackgroundWorker。

相反,您应该直接在循环内更新进度条。

+0

当你说我的工作正在UI线程上完成时,你是否说因为dispTimer_Tick()在UI线程上,所以当它创建BackgroundWorker时它也在UI线程上? – LobalOrning 2010-11-18 19:09:35

+0

@Lobal:BackgroundWorker将在后台线程上运行。但是,您认为'dispatcher.BeginInvoke'有什么作用? – SLaks 2010-11-18 19:10:00

+0

将操作放入UI线程队列中。我需要在那里做循环,因为这些列表绑定到用户界面,我不知道我怎么能够“刷新”这些列表。对不起,如果我的工作是马虎,我是一个非常新的编码器。 – LobalOrning 2010-11-18 19:13:29