在主线程中运行代码 [英] Run code in main thread

查看:65
本文介绍了在主线程中运行代码的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

它与许多问题相似,但不完全是.我需要像 BeginInvoke 之类的东西用于 Winforms,但不仅仅用于 Winforms.所以我需要单一的方法,适用于任何类型的应用程序,所以我打电话

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)
{
   ...
}

它应该可以工作,可以从控制台、winforms、wpf 等调用.我看到的所有方法都是将 BeginInvoke 用于 winforms,将 Dispatcher.Invoke 用于 WPF 等.但我应该从库中调用它,但我不知道从哪里调用它.并且它也应该对调用代码透明,因此它不应该传递诸如指向调用主线程等的指针之类的东西,lib 应该从环境本身获取这些信息,而不是从用户代码中获取,当然也没有任何全局变量.

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.

我尝试使用 Task.ConfigureAwait,但没有用.

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

我找到了这个

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

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).

但我希望这是可能的.

测试代码:

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.

推荐答案

试试这个

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

这篇关于在主线程中运行代码的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆