Frage

Ich benutze DispatcherTimer weil ich brauche eine Operation alle paar Minuten zu tun. Innerhalb dieses nenne ich eine BackgroundWorker meine Arbeit zu tun, und dann den Dispatcher an den Timer angebracht verwenden meine UI zu aktualisieren. Ich denke, der Fehler erhalte ich muß mit dem Timer zu tun, aber ich bin nicht sicher. Ist der Dispatcher getan oder die Background? Wie kann ich tun, um den Report innerhalb der foreach?

Der Fehler:

  

Diese Operation hatte bereits   OperationCompleted sie aufgefordert hatte und   weitere Anrufe sind illegal.

dabei ist:

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

Hier ist die vereinfachte:

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

EDIT: Stacktrace:

 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()
War es hilfreich?

Lösung

Ablauf der Ereignisse

  1. DoWork heißt
  2. DoWork puts "AllEmployees.Clear ();" in der Dispatcher-Warteschlange
  3. DoWork abgeschlossen ist
  4. Der Disponent sieht "AllEmployees.Clear ();" und beginnt die Verarbeitung dieser Funktion.

Ich schlage vor, mit Dispatcher.Invoke (die sofort läuft) nur auf die Schritte, die tatsächlich UI Interaktion haben.

Andere Tipps

Da Ihre Arbeit auf dem UI-Thread ausgeführt wird, sollten Sie keine Backgroundüberhaupt.

Stattdessen sollten Sie die Fortschrittsbalken direkt innerhalb der Schleife aktualisieren.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top