이것은 .NET 모니터/잠금 문의 버그입니까 아니면 MessageBox.show가 다르게 작동합니까?

StackOverflow https://stackoverflow.com/questions/585535

  •  06-09-2019
  •  | 
  •  

문제

승리 양식에 두 개의 버튼이 있다고 상상해보십시오. 사용자가 아래 코드로 "버튼 1"을 누를 때 동작은 무엇이라고 생각하십니까?

한 번에 5 개의 메시지 상자를 모두 표시해야합니까, 아니면 하나씩 하나 -Messessbox.show 문이 잠금 문 안에 있습니까?

public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
    }

    private static readonly object lockobject = new object();

    private void button1_Click(object sender, EventArgs e)
    {
        var action = new Action(function);
        for(int i = 0; i< 5; i++)
        {
            action.BeginInvoke(null, null);
        }
    }

    private void function()
    {
        if (button2.InvokeRequired)
        {
            var func = new Action(function);
            button2.Invoke(func);
        }
        else
        {
            lock (lockobject)
            {
                MessageBox.Show("Testing");
            }
        }
    }
}

이제 MessageBox.show를 다른 문장으로 바꾸면 한 번에 하나씩 문장을 실행하면 다른 스레드는 한 번에 하나씩 기다립니다.

도움이 되었습니까?

해결책

Invokerequired가 False 일 때 잠금 문이 실행되므로 잠금 장치는 모두 동일한 (메인) 스레드에서 실행됩니다. 따라서 자물쇠가 차단되지 않습니다.

MessageBox를 차단하려면 ShowDialog를 대신 사용하십시오.

다른 팁

  1. 잠금은 다른 스레드가 잠금 장치를 소유하고 동일한 스레드에서 동일한 객체를 여러 번 잠그는 경우에만 차단됩니다. 그렇지 않으면 현재 스레드를 기다리는 동안 현재 스레드를 차단 한 후 즉각적인 교착 상태가됩니다.

  2. Control.beginInvoke는 다른 스레드에서 코드를 실행하지 않으며 컨트롤을 위해 스레드 펌핑 메시지에서 코드를 항상 실행하여 컨트롤 입력 큐에 메시지를 게시 한 다음 메시지가 도착하면 코드를 실행하여 수행합니다.

2로 인해 코드가 다중 스레드가 전혀 없기 때문에 모든 것이 동일한 스레드에서 실행됩니다. 이렇게하면 여러 스레드 잠금 장치가 없으면 아무것도하지 않으면 아무것도하지 않습니다.

UI 스레드가 MessageBox Life-Cycle에서 메시지를 펌핑하고 있다고 생각합니다. 잠금 장치가 재진입되어 (그리고 UI 스레드가 매번 코드를 실행하고 있기 때문에, 위의 원인이됩니다. 아마도 주인을 통과시킬 것입니다 (this) 메시지 상자에? (잠깐 시도 할게 ...).

당신은 그것을 더 강력하게 차단할 수 있지만, 그것은 그림을 차단합니다 ( "응답하지 않음"등).

나는 NIR에 동의합니다. 기능을 아래의 기능으로 변경 한 후에는 동일한 스레드에서 실행중인 것을 테스트 할 수 있습니다 (놀랍게도).

private void function()
{
   if (button2.InvokeRequired)
   {
        var func = new Action(function);
        button2.Invoke(func);
   }
   else
   {
        lock (lockobject)
        {
            int threadId = Thread.CurrentThread.ManagedThreadId;
            MessageBox.Show("Testing. Running on thread "+threadId);
        }
    }
}

따라서 UI 스레드가 잠금 장치로 인해 차단되지 않습니다. 결론은 STA 스레드가 적절한 멀티 스레드 프로그래밍과 호환되지 않는다는 것입니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top