Вызовите метод из потока 1 в поток 2? - PullRequest
0 голосов
/ 04 июля 2018

Первый: Что я хочу сделать?

  1. Я хочу запустить несколько заданий в одном потоке, например, я хочу создать поток для вычислений и всегда запускать методы внутри него.

  2. Получите указатель, такой как SynchronizationContext.Current или Thread.CurrentThread, чтобы получить доступ к текущей работе задания.

3. Кроссплатформенный способ, подобный Net Standard.

Второе: Пример-1 (CrossPlatform-Working) Мой пример не работает, потому что метод Post и Send в SynchronizationContext не работают

 class Program
{
    static void Main(string[] args)
    {
        SynchronizationContext contextThread1 = null;
        SynchronizationContext contextThread2 = null;
        Thread thread1, thread2 = null;
        thread1 = new Thread(() =>
        {
            SynchronizationContext.SetSynchronizationContext(new SynchronizationContext());
            contextThread1 = SynchronizationContext.Current;
            while (true)
            {
                Thread.Sleep(1000);
                if (contextThread2 != null)
                {
                    contextThread2.Post((state) =>
                    {
                        //Thread.CurrentThread == thread2 always false because the method is not runnig from thread 2
                        Console.WriteLine("call a method from thread 1 for thread 2 :" + (Thread.CurrentThread == thread2));
                    }, null);
                }
            }
        });
        thread1.IsBackground = true;
        thread1.Start();

        thread2 = new Thread(() =>
        {
            SynchronizationContext.SetSynchronizationContext(new SynchronizationContext());
            contextThread2 = SynchronizationContext.Current;
            while (true)
            {
                Thread.Sleep(1000);
                if (contextThread1 != null)
                {
                    contextThread1.Post((state) =>
                    {

                        //Thread.CurrentThread == thread1 always false because the method is not runnig from thread 1
                        Console.WriteLine("call a method from thread 2 for thread 1 :"+(Thread.CurrentThread == thread1));
                    }, null);
                }
            }
        });
        thread2.IsBackground = true;
        thread2.Start();

        Console.ReadKey();
    }
}

Пример-2: (Нет кросс-платформ, потому что Windowsbase.dll): этот пример работает нормально, но это не кроссплатформенный.

    class Program
{
    static void Main(string[] args)
    {
        Dispatcher contextThread1 = null;
        Dispatcher contextThread2 = null;

        Thread thread1, thread2 = null;
        thread1 = new Thread(() =>
        {
            contextThread1 = Dispatcher.CurrentDispatcher;
            Dispatcher.Run();
        });
        thread1.IsBackground = true;
        thread1.Start();

        thread2 = new Thread(() =>
        {
            contextThread2 = Dispatcher.CurrentDispatcher;
            Dispatcher.Run();
        });
        thread2.IsBackground = true;
        thread2.Start();

        while (true)
        {
            Thread.Sleep(1000);
            if (contextThread2 != null)
            {
                contextThread2.Invoke(new Action(() =>
                {
                    //Thread.CurrentThread == thread2 always false because the method is not runnig from thread 2
                    Console.WriteLine("call a method from thread 1 for thread 2 :" + (Thread.CurrentThread == thread2));
                }));
            }
            if (contextThread1 != null)
            {
                contextThread1.Invoke(new Action(() =>
                {
                    Console.WriteLine("call a method from thread 2 for thread 1 :" + (Thread.CurrentThread == thread1));
                }));
            }
        }
        Console.ReadKey();
    }
}

1 Ответ

0 голосов
/ 04 июля 2018

В наши дни вы всегда должны использовать инструмент, чтобы облегчить вашу жизнь, где это возможно. В этом случае вы должны использовать Microsoft Reactive Framework. Просто NuGet "System.Reactive" и добавьте using System.Reactive.Linq;.

Тогда вы можете сделать это:

void Main()
{
    var thread1 = new EventLoopScheduler();
    var thread2 = new EventLoopScheduler();

    Action action = () => Console.WriteLine(Thread.CurrentThread.ManagedThreadId);

    action();

    thread1.Schedule(action);

    Thread.Sleep(1000);

    thread2.Schedule(action);

    Thread.Sleep(1000);

    thread2.Schedule(() =>
    {
        action();
        thread1.Schedule(action);
    });

    Thread.Sleep(1000);

    action();
}

Тип вывода, который я получаю:

11
12
14
14
12
11

Если вы будете следовать коду, вы увидите, что он правильно распределяется по каждому потоку.

Если вы хотите завершить работу, просто наберите .Dispose() на каждом EventLoopScheduler.

...