如何退出(停止)我的调度员?

时间:2014-07-18 09:02:36

标签: c# wpf dispatcher

当用户点击按钮时,我想停止在main()中启动的调度程序。

    private void button_start_Click(object sender, RoutedEventArgs e)
    {
        ...
            Camera.EventFrame -= onFrameEventFocusCam;  //unsubscribe event

            while (!Dispatcher.HasShutdownStarted)
            {
                // test if Dispatcher started shutdown  --> ok, it does but never finishs...!
            }
        ...
    }        


    private void onFrameEventFocusCam(object sender, EventArgs e)
    {
       ...

        Dispatcher.Invoke(new Action(() =>
        {
            // Convert bitmap to WPF-Image
            var bmp = new Bitmap(bitmap);
            var hBitmap = bmp.GetHbitmap();

            System.Windows.Media.ImageSource wpfBitmap = System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap(
            hBitmap, IntPtr.Zero, Int32Rect.Empty, BitmapSizeOptions.FromEmptyOptions());

            image_fokus.Source = wpfBitmap;
            image_fokus.Stretch = System.Windows.Media.Stretch.UniformToFill;


            DeleteObject(hBitmap);
            bitmap.Dispose();

        }));
        GC.Collect();
    }

当我运行此代码时,我在onFrameEventFocusCam

中停止时收到以下错误消息
  Error-Message: Thread was interrupted from a waiting state.

3 个答案:

答案 0 :(得分:2)

当您致电BeginInvokeDispatcher时,会导致调度员异步关闭 ;它仍然需要在关闭之前完成当前调度程序帧的处理。但是,由于您在循环中等待调度程序关闭,因此当前帧永远不会完成,因此调度程序无法完成关闭。相反,您可以订阅ShutdownFinished事件以检测调度程序何时关闭。

至于您在onFrameEventFocusCam中遇到的错误,我认为这是因为调度员正在关闭,因此它无法处理Invoke;来自文档:

  

关闭过程开始后,队列中的所有待处理工作项都将中止。

我不确定你要做什么,但关闭主调度员很可能这样做,因为它会有效地停止应用...

答案 1 :(得分:2)

目前还不清楚你的初衷是什么。

此代码应该(几乎)永久挂起,因为HasShutdownStarted在应用程序退出之前不会变为真。

while (!Dispatcher.HasShutdownStarted)
            {
                // test if Dispatcher started shutdown  --> ok, it does but never finishs...!
            }

此代码计划在UI线程上执行委托。看起来很不错。

private void onFrameEventFocusCam(object sender, EventArgs e)
    {
       ...

        Dispatcher.Invoke(new Action(() =>
        {
        ...
       }
    }

此代码看起来可能有问题,因为如果DeleteObject实际释放句柄,则句柄可能会释放两次,一次在Delete中,一次在Dispose中。这可以扔掉。

DeleteObject(hBitmap);
bitmap.Dispose();

答案 2 :(得分:0)

要在主应用程序线程上运行停止调度程序,您应该调用从传递给Dispatcher.Invoke的操作返回。