首页 > 解决方案 > 需要一种干净的方式在 C# 中的两个执行线程之间进行握手

问题描述

A 需要强制我的代码的某些功能在主线程上运行。我们正在与单线程黑匣子交谈,如果我从工作线程运行,我的性能是不可接受的。几个月来我一直在解决这个问题,方法是保存当前的同步上下文,然后使用 Post 调用一个函数,然后在主线程中执行。我知道这是为 GUI 设计的,我不确定它为什么一直有效,但是当我们使用我必须兼容的旧版本的基础软件时,它现在已经不一致了。

我写了这个基本的例子来说明我的问题。我运行一个在新线程中运行的任务,并且在某个时刻我希望该线程能够要求主线程执行一些操作,然后我希望工作线程能够继续。

这是当前的输出:

Main (ThreadId = 1)
RunTask (ThreadId = 3)
CallBack (ThreadId = 4)  << I want this to be ThreadId 1

如果它与当前解决方案接近,任何帮助都会非常好,甚至更好,因为我们距离发布还有几天的时间,我担心重大重写可能会导致更多问题。谢谢!

public class Test
{
    internal static SynchronizationContext _context;    
    internal static bool _busy = false;

    static void Main(string[] args)
    {
        Console.WriteLine("Main (ThreadId = " + Thread.CurrentThread.ManagedThreadId + ")");

        SynchronizationContext.SetSynchronizationContext(new SynchronizationContext());

        _context = SynchronizationContext.Current;

        Task.Run(() => RunTask());

        Console.Read();
    }

    public static Task RunTask()
    {
        Console.WriteLine("RunTask (ThreadId = " + Thread.CurrentThread.ManagedThreadId + ")");

        _busy = true;

        _context.Post(new SendOrPostCallback((o) =>
        {
            CallBack(null,
                     EventArgs.Empty);
        }),
                       null);

        while (_busy == true)
        {

        }

        return null;
    }

    public static void CallBack(object sender, EventArgs e)
    {
        Console.WriteLine("CallBack (ThreadId = " + Thread.CurrentThread.ManagedThreadId + ")");
    }
}

标签: c#multithreading

解决方案


谢谢大家的建议。我最终发现了这个:

https://stackoverflow.com/a/20071498/10312402

类似的解决方案解决了我的问题。这是我现在的示例程序:

public static class DispatcherHelper
{
    public static void DoEvents()
    {
        DispatcherFrame frame = new DispatcherFrame();
        Dispatcher.CurrentDispatcher.BeginInvoke(DispatcherPriority.Background, new DispatcherOperationCallback(ExitFrame), frame);
        Dispatcher.PushFrame(frame);
    }

    private static object ExitFrame(object frame)
    {
        ((DispatcherFrame)frame).Continue = false;
        return null;
    }
}

public class Test
{
    internal static bool _busy = false;

    internal static Dispatcher _dispatcher;

    static void Main(string[] args)
    {
        Console.WriteLine("Main (ThreadId = " + Thread.CurrentThread.ManagedThreadId + ")");

        _dispatcher = Dispatcher.CurrentDispatcher;

        Task.Run(() => RunTask());

        DispatcherHelper.DoEvents();
        DispatcherHelper.DoEvents();
    }

    public static Task RunTask()
    {
        Console.WriteLine("RunTask (ThreadId = " + Thread.CurrentThread.ManagedThreadId + ")");

        _busy = true;

        _dispatcher.Invoke(new Action(CallBack));

        while (_busy == true)
        {

        }

        return null;
    }

    public static void CallBack()
    {
        Console.WriteLine("CallBack (ThreadId = " + Thread.CurrentThread.ManagedThreadId + ")");

        _busy = false;
    }
}

使用该代码,我得到了我想要的输出:

Main (ThreadId = 1)
RunTask (ThreadId = 3)
CallBack (ThreadId = 1)

将其重新插入我的完整程序也可以。


推荐阅读