c# - WPF 执行两个交替的 UI 任务

标签 c# .net wpf multithreading

我有一个带有 Helix3DToolkit Graphics 的 WPF UI。

那里有两个按钮,

第一个按钮 - 添加一些 Visual3D 对象到其中。

第二个按钮 - 使用
将当前 UI 的屏幕截图保存为 jpeg 图像 截图代码:

Viewport3DHelper.Export(vp.Viewport, filename);

所有这一切手动工作正常。但现在我想把它变成自动的。 (按钮 1 和 2 的几轮交替 Action 。即我只想按一个按钮,这将添加一些框,保存屏幕截图,添加更多,保存屏幕截图等)

我可以使用以下代码以编程方式控制按钮:

ButtonAutomationPeer peer = new ButtonAutomationPeer(MyButton);
IInvokeProvider invokeProv = peer.GetPattern(PatternInterface.Invoke) as IInvokeProvider;
invokeProv.Invoke();

但是当我这样做时,我得到的只是同一 UI 的多个副本。 (我相信这是由于 UI 线程的性质造成的)

我找到了一个部分解决方案,就是使用,

TaskScheduler scheduler = TaskScheduler.FromCurrentSynchronizationContext();
CancellationToken cancellationToken = new CancellationToken();

Task.Factory.StartNew(() => GetScreenShotAction()).ContinueWith(w =>
{
            AddBoxes();
}, cancellationToken, TaskContinuationOptions.None, scheduler);

但是,这也不能正常工作(它是随机工作的,当我只截取 2 个屏幕截图时,但从不超过 2 个)。这可能是因为之前和之后的操作都在 UI 线程上。

任何关于如何完成这项工作的想法都将不胜感激。

我还使用 VC# 2010 和 .NET 4 框架。所以不能使用 asyncawait

谢谢!

更新

我已经在 GetScreenShotAction 方法中使用 this.Dispatcher.Invoke((Action)(() => { ... }));。并且,另一个操作 AddBoxes 在同一个线程上。

另外,它是随机工作的,所以我猜是因为我正在调用 Dispatcher,所以两者在技术上仍然发生在同一个线程上。

最佳答案

我怀疑您需要等待 UI 呈现(在通过添加按钮修改可视化树之后),然后再截取屏幕截图。

This article展示了如何使用带有 DispatcherPriority.Render 的调度程序来获取代码以等待所有渲染完成后再继续。

引用文章:

When the DispatcherPriority is set to Render (or lower), the code will then execute all operations that are of that priority or higher. In the example, the code already sets label1.Content to something else, which will result in a render operation. So by calling Dispatcher.Invoke, the code essentially asks the system to execute all operations that are Render or higher priority, thus the control will then render itself (drawing the new content). Afterwards, it will then execute the provided delegate (which is our empty method).

刷新扩展方法的代码:

public static class ExtensionMethods
{
   private static Action EmptyDelegate = delegate() { };

   public static void Refresh(this UIElement uiElement)
   {
      uiElement.Dispatcher.Invoke(DispatcherPriority.Render, EmptyDelegate);
   }
}

像这样使用它:

AddBoxes();
MyControlContainer.Refresh();
TakeScreenShot();

MyControlContainer 是一个 UIElement,也许是您添加框的容器?

关于c# - WPF 执行两个交替的 UI 任务,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27817903/

相关文章:

c# - 从线程调用 Invoke/BeginInvoke

c# - 在 wpf C# 中删除数据网格行之前删除确认

wpf - 在 Wpf 中关闭另一个窗口

C#,visual studio 2010,如何停止方法,线程?

c# - WebService 不反序列化某些对象

C# 将类类型作为参数传递

c# - 有没有一种简单的方法来解析 C# 中的结构化文本文件?

c# - 如何将格式为 "dd/mm"的日期与 DateTime.Now 进行比较

wpf - 操作事件未触发

c# - 协变和逆变混淆