How to run something in the STA thread?

后端 未结 5 1264
礼貌的吻别
礼貌的吻别 2020-11-29 03:17

In my WPF application I do some async communication (with server). In the callback function I end up creating InkPresenter objects from the result from server. This requires

相关标签:
5条回答
  • 2020-11-29 03:47

    It should be good enough to call it on the UI thread. Therefore, use a BackgroundWorker and on the RunWorkerAsyncCompleted, you can then do the creation of the inkPresenter.

    0 讨论(0)
  • 2020-11-29 04:00

    You can use the Dispatcher class to execute the method call on the UI-Thread. The Dispatcher provides the static property CurrentDispatcher to get the dispatcher of a thread.

    If your object of the class, that creates the InkPresenter, is created on the UI-Thread, then the CurrentDispatcher method returns the Dispatcher of the UI-Thread.

    On the Dispatcher you can call the BeginInvoke-method to call the specified delegate asynchronously on the thread.

    0 讨论(0)
  • 2020-11-29 04:05

    I have just used the following to get clipboard content from the STA thread. Thought I would post to maybe help someone in the future...

    string clipContent = null;
    Thread t = new Thread(
        () =>
        {
            clipContent = Clipboard.GetText();
        });
    t.SetApartmentState(ApartmentState.STA);
    t.Start();
    t.Join();
    
    // do stuff with clipContent
    
    t.Abort();
    
    0 讨论(0)
  • 2020-11-29 04:06

    You can start STA Threads like so:

        Thread thread = new Thread(MethodWhichRequiresSTA);
        thread.SetApartmentState(ApartmentState.STA); //Set the thread to STA
        thread.Start(); 
        thread.Join(); //Wait for the thread to end
    

    The only problem is that your result object must be passed along somehow.. You can use a private field for that, or dive into passing along parameters into threads. Here I set the foo data in a private field and start up the STA Thread to mutate the inkpresenter!

    private var foo;
    public void SearchForFooCallbackMethod(IAsyncResult ar)
    {
        foo = GetFooFromAsyncResult(ar); 
        Thread thread = new Thread(ProcessInkPresenter);
        thread.SetApartmentState(ApartmentState.STA);
        thread.Start();
        thread.Join(); 
    }
    
    private void ProcessInkPresenter()
    {
        var inkPresenter = XamlReader.Parse(foo.Xaml) as InkPresenter;
    }
    

    Hope this helps!

    0 讨论(0)
  • 2020-11-29 04:11

    It's a bit of a hack, but I would use XTATestRunner So your code will look like:

        public void SearchForFooAsync(string searchString)
        {
            var caller = new Func<string, Foo>(_patientProxy.SearchForFoo);
            caller.BeginInvoke(searchString, new AsyncCallback(SearchForFooCallbackMethod), null);
        }
    
        public void SearchForFooCallbackMethod(IAsyncResult ar)
        {
            var foo = GetFooFromAsyncResult(ar); 
            InkPresenter inkPresenter;
            new XTATestRunner().RunSTA(() => {
                inkPresenter = XamlReader.Parse(foo.Xaml) as InkPresenter;
            });
        }
    

    as a bonus it's possible to catch exceptions thrown in STA (or MTA) thread like this:

    try
    {
        new XTATestRunner().RunSTA(() => {
            throw new InvalidOperationException();
        });
    }
    catch (InvalidOperationException ex)
    {
    }
    
    0 讨论(0)
提交回复
热议问题