如何将矢量格式的图形从一个线程返回到另一个线程?

发布于 2024-12-11 14:37:22 字数 649 浏览 0 评论 0原文

我正在设计一个系统,其中有多个并行运行的任务。它们中的每一个都会获得一些输入,并且应该以矢量格式返回图形输出。

然后,主 WPF 应用程序应根据用户请求绘制任何这些任务的结果。目前我使用 Canvas、矩形和其他 System.Windows.Shapes 作为我的图形矢量格式作为输出。任务完成后,我将 Canvas 子项一一添加到 GUI 实际 Canvas 中。

但是,我刚刚发现 UI 元素不能在主线程(所谓的 Dispatcher 线程)之外的任何其他线程上创建。 http://social.msdn.microsoft.com/Forums/ar/wpf/thread/c4600372-342c-4ee4-b49c-d9abf967fc93
将 UI 元素的创建(如上面的文章中所建议的)委托给主线程对我来说不是一个选择,因为它们应该在用户请求输出时显示,而不是在任务完成时显示。

实际上我不需要在另一个线程中创建 UI 元素,我只是想要一种方便的方法来创建矢量图形并稍后在 WPF 应用程序中显示它们。

有人知道该怎么做吗?

I am designing a system in which there are multiple tasks which run in parallel. Each one of them gets some input, and should return graphical output in vector format.

The main WPF application should then draw the result of any of these tasks, upon user request. Currently I am using Canvas, Rectangle and other System.Windows.Shapes as my graphical vector format as output. When the task is completed, I take the Canvas children, and add them one-by-one to the GUI actual Canvas.

However, I've just discovered that UI elements cannot be created on any other thread than the main thread (so called Dispatcher thread).
http://social.msdn.microsoft.com/Forums/ar/wpf/thread/c4600372-342c-4ee4-b49c-d9abf967fc93
Delegating the creation of the UI elements, (As suggested in the article above) to the main thread is not an option for me, since they should be shown whenever the user asks for the output, and not when the task is finished.

Actually I don't need to create UI elements in another thread, I just want a convenient method to create vector graphics and show them later in WPF application.

Does anyone has an idea what to do?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

青萝楚歌 2024-12-18 14:37:22

在启动并行活动之前捕获 UI(主线程)的 SynchronizationContext。并在捕获的 SynchronizationContext 引用上调用(只要需要)Send 方法,以便将消息推送到 UI 线程中。
MSDN 上的 SynchronizationContext

public partial class MainWindow : Window
    {
        SynchronizationContext UISyncContext;
        YourTaskOutPut Myresult;
        public MainWindow()
        {
            InitializeComponent();
        }
        public StartProcessingVGraphics()
        {
            //Let say this method is been called from UI thread. i.e on a button click
            //capture the current synchronization context

            UISyncContext=TaskScheduler.FromCurrentSynchronizationContext;

            //Start your VGraph processing using TPL in background and store result to Myresult (of type YourTaskOutPut)
            result= GetMeTaskResults();

        }

        public GetMeResultNow()
        {
            //Let's say this is is the method which user triggers at
            //some point in time ( with the assumption that we have Myresult in hand)

            if(UISyncContext!=null)
                UISyncContext.Send(new SendOrPostCallback(delegate{ PutItInUI }),null);

            //Use Send method - to send your request synchronously
            //Use Post method- to send your request asynchronously
        }
        void PutItInUI()
        {
            //this method help you to put your result in UI/controls
        }

Capture SynchronizationContext of the UI ( main thread) before starting the parallel activities. And call (whenever you need) Send method on the captured SynchronizationContext reference in order to push the message into UI thread.
MSDN on SynchronizationContext

public partial class MainWindow : Window
    {
        SynchronizationContext UISyncContext;
        YourTaskOutPut Myresult;
        public MainWindow()
        {
            InitializeComponent();
        }
        public StartProcessingVGraphics()
        {
            //Let say this method is been called from UI thread. i.e on a button click
            //capture the current synchronization context

            UISyncContext=TaskScheduler.FromCurrentSynchronizationContext;

            //Start your VGraph processing using TPL in background and store result to Myresult (of type YourTaskOutPut)
            result= GetMeTaskResults();

        }

        public GetMeResultNow()
        {
            //Let's say this is is the method which user triggers at
            //some point in time ( with the assumption that we have Myresult in hand)

            if(UISyncContext!=null)
                UISyncContext.Send(new SendOrPostCallback(delegate{ PutItInUI }),null);

            //Use Send method - to send your request synchronously
            //Use Post method- to send your request asynchronously
        }
        void PutItInUI()
        {
            //this method help you to put your result in UI/controls
        }
念三年u 2024-12-18 14:37:22

我找到了另一个可能的答案。当图形不是绘制而是定义时,应该使用 GeometryDrawing 类而不是 Shapes,就像我的情况一样。它具有 Freeze 方法,允许通过不同的线程传递它,因为它是不可变的。
摘自微软MSDN:

System.Windows.Shapes.Shape 类具有 Fill、Stroke 和 Geometry 及其派生类所缺乏的其他渲染属性。 Shape 类是一个 FrameworkElement,因此参与布局系统;它的派生类可以用作任何支持 UIElement 子元素的元素的内容。

另一方面,Geometry 类仅定义形状的几何形状,并且无法渲染自身。由于其简单性,它具有更广泛的用途。

MSDN 参考

I've found another possible answer. One should use GeometryDrawing classes instead of Shapes when graphics are not drawn but rather defined, as in my case. It has the Freeze method, which allows passing it through different threads, because it is immutable.
Taken from Microsoft MSDN:

The System.Windows.Shapes.Shape class has a Fill, Stroke, and other rendering properties that Geometry and its derived classes lack. The Shape class is a FrameworkElement and therefore participates in the layout system; its derived classes can be used as the content of any element that supports UIElement children.

The Geometry class, on the other hand, simply defines the geometry of a shape, and cannot render itself. Because of its simplicity, it has a wider range of uses.

MSDN reference

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文