如何使用c#中的winapi32函数在线程之间发送消息?

如何使用c#中的winapi32函数在线程之间发送消息?,c#,multithreading,winapi,C#,Multithreading,Winapi,我有一个任务,需要从另一个线程向一个线程发送消息。 我有一个类来完成这项任务,它是: public class MyThread { public Thread Thrd { get; set; } public MyThread Next { get; set; } public MyThread() { Thrd = new Thread(Work); } public void Start() {

我有一个任务,需要从另一个线程向一个线程发送消息。 我有一个类来完成这项任务,它是:

public class MyThread
{
    public Thread Thrd { get; set; }
    public MyThread Next { get; set; }


    public MyThread()
    {
        Thrd = new Thread(Work);
    }

    public void Start()
    {
        Thrd.Start();
    }

    private void Work()
    {
        while (true)
        {
            if (//Has message to receive)
            {
                //Get message and do work
                //Send message to the Next.Thrd
            }
        }
    }
    
}
作为一个消息,我只需要发送一个整数。我发现像PostThreadMessageA和GetMessageA这样的函数对我很有用,是吗?而且,这些需要一个线程句柄,我怎样才能得到它?最后,是否有一个函数可以检查此线程是否有要接收的消息(我可以将其替换为“/”要接收的消息)

这些需要一个线程句柄,我怎样才能得到它

您可以使用在线程启动后获取线程ID

是否有功能检查是否有消息要接收 这条线用的是什么

是,/(
GetMessage
将等待消息到达,但
PeekMessage
不会等待消息在返回前发布。)

以下是win32解决方案。在主线程中创建两个线程thread1、thread2(thread1.Next=thread2)。主线程将数据发送到thread1,然后thread1接收消息并将其数据发送到thread2:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace ConsoleApp
{
    public class MyThread
    {
        
        [StructLayout(LayoutKind.Sequential)]
        public struct POINT
        {
            public int x;
            public int y;
        }
        [StructLayout(LayoutKind.Sequential)]
        public struct MSG
        {
            public IntPtr hwnd;
            public int message;
            public UIntPtr wParam;
            public IntPtr lParam;
            public int time;
            public POINT pt;
            public int lPrivate;
        }
        [DllImport("Kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)]
        public static extern int GetCurrentThreadId();
        
        [DllImport("User32.dll",SetLastError = true,CharSet =CharSet.Auto)]
        public static extern bool PostThreadMessage(int idThread, uint Msg, IntPtr wParam, IntPtr lParam);

        [DllImport("User32.dll", SetLastError = true, CharSet = CharSet.Auto)]
        public static extern bool GetMessage(out MSG Msg, IntPtr hWnd, uint wMsgFilterMin, uint wMsgFilterMax);
        [DllImport("User32.dll", SetLastError = true, CharSet = CharSet.Auto)]
        public static extern bool PeekMessage(out MSG Msg, IntPtr hWnd, uint wMsgFilterMin, uint wMsgFilterMax,uint wRemoveMsg);
        public static uint WM_USER = 0x0400;
        public Thread Thrd { get; set; }
        public MyThread Next { get; set; }
        public int ThreadId { get; set; }
        public int data { get; set; }
        public MyThread()
        {
            Thrd = new Thread(Work);
            ThreadId = -1;
        }

        public void Start()
        {
            Thrd.Start();
        }
        public static bool SendTo(int data, MyThread target_thread)
        {
            IntPtr lparam = new IntPtr(data);
            return PostThreadMessage(target_thread.ThreadId, WM_USER, IntPtr.Zero, lparam);
        }
        private void Work()
        {
            ThreadId = GetCurrentThreadId();
            data = ThreadId;
            while (true)
            {
                MSG msg = new MSG();
                IntPtr hwnd = new IntPtr(-1);
                if (GetMessage(out msg, IntPtr.Zero, 0, 0))
                {
                    Console.WriteLine("received : " + msg.lParam.ToInt32());
                    if (Next != null)
                        SendTo(data, Next);
                }
            }
        }

    }
    class Program
    {
        static void Main(string[] args)
        {
            MyThread thread1 = new MyThread();
            MyThread thread2 = new MyThread();
            thread1.Next = thread2;
            thread1.Start();
            thread2.Start();

            //To Do
            //To Ensure that the thread has been started, and the thread ID has been obtained through GetCurrentThreadId
            Thread.Sleep(1000); 

            MyThread.SendTo(50, thread1);

            //To Do
        }
    }
}

为了得到我想要的,我使用了以下函数:

    [DllImport("user32.dll")]
    [return: MarshalAs(UnmanagedType.Bool)]
    private static extern bool PeekMessage(
        out InternalMessage lpInternalMessage,
        IntPtr hWnd,
        uint wMsgFilterMin,
        uint wMsgFilterMax,
        uint wRemoveMsg
    );

    [DllImport("user32.dll", SetLastError = true)]
    [return: MarshalAs(UnmanagedType.Bool)]
    private static extern bool PostThreadMessage(
        uint threadId,
        uint msg,
        UIntPtr wParam,
        IntPtr lParam
        );

    [DllImport("kernel32.dll")]
    public static extern uint GetCurrentThreadId();
我还需要定义这样一个结构:

[StructLayout(LayoutKind.Sequential)]
public struct InternalMessage
{
    public IntPtr hwnd;
    public uint message;
    public UIntPtr wParam;
    public IntPtr lParam;
    public int time;
    public Point pt;
    public int lPrivate;
}

PostMessage()需要一个窗口(不是线程)、一个消息循环和一个线程安全队列(由操作系统提供)。您没有或不需要的基础架构。这只是生产者-消费者问题的一个解决方案,是.NET中的标准解决方案。是的,我看到了一个使用ConcurrentQueue的解决方案,但我需要使用这些api函数。我可能是指PostThreadMessageA而不是PostMessage为什么需要使用这些函数?很可能你的想法是错误的。@DavidHeffernan我知道这些函数很容易出错,但使用它们是我任务的一部分。你是想解决问题,还是只想调用这些函数?