Как вернуть векторную графику из одного потока в другой? - PullRequest
2 голосов
/ 24 октября 2011

Я разрабатываю систему, в которой параллельно выполняются несколько задач.Каждый из них получает некоторый ввод и должен возвращать графический вывод в векторном формате.

Основное приложение WPF должно затем выводить результат любой из этих задач по запросу пользователя.В настоящее время я использую Canvas, Rectangle и другие System.Windows.Shapes в качестве графического векторного формата в качестве вывода.Когда задача выполнена, я беру детей Canvas и добавляю их один за другим к фактическому холсту GUI.

Однако я только что обнаружил, что элементы пользовательского интерфейса не могут быть созданы ни в каком другом потоке, кроме основного (так называемого потока Dispatcher).http://social.msdn.microsoft.com/Forums/ar/wpf/thread/c4600372-342c-4ee4-b49c-d9abf967fc93
Передача создания элементов пользовательского интерфейса (как предложено в статье выше) основному потоку для меня не вариант, поскольку они должны отображаться всякий раз, когда пользователь запрашивает вывод, ине когда задача закончена.

На самом деле мне не нужно создавать элементы пользовательского интерфейса в другом потоке, я просто хочу удобный метод для создания векторной графики и отображения ее позже в приложении WPF.

У кого-нибудь есть идеи, что делать?

Ответы [ 2 ]

1 голос
/ 24 октября 2011

Захват SynchronizationContext пользовательского интерфейса (основной поток) перед началом параллельных действий.И вызовите (когда вам нужно) метод Send для захваченной ссылки SynchronizationContext, чтобы отправить сообщение в поток пользовательского интерфейса. 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
        }
0 голосов
/ 25 октября 2011

Я нашел другой возможный ответ. Нужно использовать классы GeometryDrawing вместо Shapes, когда графика не прорисована, а скорее определена, как в моем случае. У него есть метод Freeze , который позволяет передавать его через разные потоки, потому что он неизменен. Взято из Microsoft MSDN:

Класс System.Windows.Shapes.Shape имеет свойства Fill, Stroke и другие свойства рендеринга, которые отсутствуют в Geometry и ее производных классах. Класс Shape является FrameworkElement и поэтому участвует в системе макетов; его производные классы могут использоваться в качестве содержимого любого элемента, который поддерживает дочерние элементы UIElement.

Класс Geometry, с другой стороны, просто определяет геометрию фигуры и не может отображаться сам. Из-за своей простоты он имеет более широкий спектр применения.

Ссылка MSDN

...