Run code in main thread

与世无争的帅哥 提交于 2021-01-02 06:23:07

问题


It's similar to many questions, but not rly. I need something like BeginInvoke for Winforms, but not for winforms only. So i need single method, that works for any type of application, so i'm calling

void ExecuteInMainContext(Action action)
{
   ...
}

and it should work, be called from Console, winforms, wpf and so on. All methods i saw was using BeginInvoke for winforms, Dispatcher.Invoke for WPF etc. But i should call it from library and i don't know from where it's called. And it also should be transparent to calling code, so it shouldn't pass something like pointer to calling main thread etc, lib should get this info itself from environment, not from user code and without any global variables, of course.

I've tried to use Task.ConfigureAwait, but it didn't help.

i found this one

You can't do this (without a lot of work) in a Console application. The mechanisms built into the TPL for marshaling the call back onto a thread all rely on the thread having an installed SynchronizationContext. This typically gets installed by the user interface framework (ie: Application.Run in Windows Forms, or in WPF's startup code, etc).

but I hope it's possible.

code for tests:

using System;
using System.Threading;

namespace Test
{
    class Program
    {
        private static void Main(string[] args)
        {

            Console.WriteLine("Main: " + Thread.CurrentThread.ManagedThreadId);
            Publisher publisher = new Publisher(Method);
            Console.ReadLine();
        }

        private static void Method(string s)
        {
            Console.WriteLine(s + " " + Thread.CurrentThread.ManagedThreadId);
        }

    }

    class Publisher
    {
        public event Action<string> Action;

        protected virtual void OnAction(string obj)
        {
            Action<string> handler = Action;
            if (handler != null)
            {
                SafeCall(() => handler(obj));
            }
        }

        private static void SafeCall(Action action)
        {
            // ???
            action(); // should write 1
        }

        public Publisher(Action<string> action)
        {
            Action = action;
            Console.WriteLine("Publisher thread: " + Thread.CurrentThread.ManagedThreadId);
            Thread thread = new Thread(() => OnAction("hello"));
            thread.Start();
        }
    }
}

so it should write same number anywhere.


回答1:


Try this

void ExecuteInMainContext(Action action)
    {
        var synchronization = SynchronizationContext.Current;
        if (synchronization != null)
        {
            synchronization.Send(_ => action(), null);//sync
            //OR
            synchronization.Post(_ => action(), null);//async
        }
        else
            Task.Factory.StartNew(action);

        //OR
        var scheduler = TaskScheduler.FromCurrentSynchronizationContext();

        Task task = new Task(action);
        if (scheduler != null)
            task.Start(scheduler);
        else
            task.Start();
    }


来源:https://stackoverflow.com/questions/20300164/run-code-in-main-thread

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!