简体   繁体   中英

WPF - Cross Thread Event

My problem is that I want to add Items in a Canvas, using a new thread. So i have multiple Methods (an example at the bottom), they generate for example an Image and set some properties. Then they should callback the generated think through an event.

The following is a part of the thread i call to generate thinks for the canvas:

    //Here I create the event in the seconde Thread

    public delegate void OnItemGenerated(UIElement elem);

    public event OnItemGenerated onItemGenerated;

    public void ItemGenerated(UIElement ui)
    {
        if (onItemGenerated != null)
            onItemGenerated(ui);
    }

    ......

    //This is how I generate for example an image

   public void addImage(int x, int y, string path, int width, int height)
    {
        System.Drawing.Bitmap bitmap = new System.Drawing.Bitmap(path);
        Image img = new Image();
        img.Source = getImage(bitmap);
        img.Width = width;
        img.Height = height;
        Canvas.SetTop(img, y);
        Canvas.SetLeft(img, x);
        Application.Current.Dispatcher.Invoke(new Action(() => { ItemGenerated(img); }), DispatcherPriority.ContextIdle);
    }

Then on the main thread I want to add the callbacked UIElement to the canvas.

banner.onItemGenerated += (ui) =>
        {
            var uiElem = ui;
            this.canvas.BeginInvoke(new Action(delegate () { this.canvas.Children.Add(uiElem); }));
        };

And this is how I start the Thread:

Thread t2 = new Thread(delegate ()
        {
            banner.GenerateImage(p);      
        });
        t2.SetApartmentState(ApartmentState.STA);
        t2.Start();

Why I do this is because some Elements need to connect to a TelNet connection. And this takes some time, so I want to add the Elements in the Canvas asyncronly.

The problem is that i cant access the Canvas because it says that i try to access a different thread.

Sorry, English is not my first language.

You don't want to use the Canvas item directly because it lives in the gui thread. The invoke you want to use should be generic one such as this one which I have as a static on my ViewModel:

public static void SafeOperationToGuiThread(Action operation)
{
    System.Windows.Application.Current?.Dispatcher?.Invoke(operation);
}

Then you can call the operation from the other thread such as:

SafeOperationToGuiThread(() =>
{
       var uiElem = ui;
       canvas.Children.Add(uiElem);                
});

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM