繁体   English   中英

在主线程中运行代码

[英]Run code in main thread

它类似于许多问题,但不是很狡猾。 我需要类似于Winforms的BeginInvoke ,但不仅仅适用于winforms。 所以我需要单一的方法,适用于任何类型的应用程序,所以我打电话

void ExecuteInMainContext(Action action)
{
   ...
}

它应该工作,从控制台,winforms,Wpf等调用。 我看到的所有方法都是使用BeginInvoke for winforms, Dispatcher.Invoke for WPF等。但我应该从库中调用它,我不知道从哪里调用它。 并且它也应该对调用代码是透明的,因此它不应该传递类似于调用主线程等的指针,lib应该从环境中获取此信息,而不是从用户代码获取,当然也没有任何全局变量。

我试过使用Task.ConfigureAwait ,但它没有帮助。

我发现了这个

您无法在控制台应用程序中执行此操作(无需大量工作)。 内置到TPL中用于将调用封送回线程的机制都依赖于具有已安装的SynchronizationContext的线程。 这通常由用户界面框架安装(即:Windows窗体中的Application.Run,​​或WPF的启动代码等)。

但我希望这是可能的。

测试代码:

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();
        }
    }
}

所以应该在任何地方写相同的数字。

试试这个

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();
    }

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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