The form behaves strangely when using STA and streams for too long

We are developing a multi-threaded game engine in C #, and we had a problem in that we need the STAThread attribute (or manually configure our threads in STA) to enable drag and drop support (AllowDrop cannot be installed without STA). However, when we turn on the STA and the update method takes longer than the draw method (as shown below), the window does not behave properly - when it clicks on the taskbar, it does not minimize or maximize how you expected It. The exact behavior is different from different systems, I think that there are some kind of race conditions.

Here is our test code:

    [STAThread]
    public static void Main()
    {
        Form form = new Form();
        form.Show();

        Barrier barrier = new Barrier(2);

        Thread updateThread = new Thread(() => {
            while (true)
            {
                barrier.SignalAndWait();
                Thread.Sleep(30); //Update
                barrier.SignalAndWait();
            }
        });
        updateThread.Start();

        while (true)
        {
            barrier.SignalAndWait();
            Thread.Sleep(15); //Draw
            barrier.SignalAndWait();
            Application.DoEvents();
        }
    }
+4
1

, Vista . WM_ACTIVATEAPP, , . , , , "" .

Barrier.SignalAndWait(). , STA. CLR - , , . , WM_ACTIVATEAPP, , 30 , . - . , . , .

, . , CLR . , . - , SynchronizationContext.Wait(). , , WindowsFormsSynchronizationContext , Wait(). Reference Source / . .

, , :

using System.Runtime.InteropServices;

class MySynchronizationContext : SynchronizationContext {
    public MySynchronizationContext() {
        base.SetWaitNotificationRequired();
    }
    public override int Wait(IntPtr[] waitHandles, bool waitAll, int millisecondsTimeout) {
        return WaitForMultipleObjects(waitHandles.Length, waitHandles, false, millisecondsTimeout);
    }

    [DllImport("kernel32.dll")]
    static extern int WaitForMultipleObjects(int nCount, IntPtr[] lpHandles,
        bool bWaitAll, int dwMilliseconds);
}

:

    System.ComponentModel.AsyncOperationManager.SynchronizationContext = 
       new MySynchronizationContext();

, SetWaitNotificationRequired() CLR, Wait() Wait(). Wait() , . , .

+5

Source: https://habr.com/ru/post/1669458/


All Articles