Убедитесь, что в потоке пользовательского интерфейса создана новая форма - PullRequest
0 голосов
/ 17 мая 2018

У меня есть несколько потоков, которые записывают в форму журнала. Какой бы поток ни имел первое сообщение, он создаст форму на лету. Я использую MyForm.InvokeRequired / .Invoke(…) для каждого обновления формы, однако код иногда блокируется с основным потоком в состоянии .WaitForWaitHandle .

Из того, что я понимаю - хотя это может быть совершенно не так - проблема в том, что иногда WorkerThread создает форму. Отныне .InvokeRequired всегда будет истинным, даже если форма впоследствии обновляется из потока пользовательского интерфейса. В последнем случае поток пользовательского интерфейса может ожидать себя?

Я надеюсь, что смогу это исправить, создав форму в самом потоке пользовательского интерфейса, но я не знаю, с какого элемента управления начинать, пока MyForm == null .

Примечание : в фоновом режиме находится многопоточный API с потоками для получения / отправки / обработки сообщений, которые мне необходимо отслеживать.

Упрощенный экзамен:

public static LogForm MyForm;

public static void AddLogLine(string inText) // is called from multiple threads
{
    if (MyForm == null) MyForm = new LogForm();

    if (MyForm.InvokeRequired)
        MyForm.Invoke(new Action<LogForm, string>(_appendText), MyForm ,inText); // deadlock, UI thread state: .WaitForWaitHandle
    else
        _appendText(MyForm ,inText);
}

1 Ответ

0 голосов
/ 18 мая 2018

Я бы порекомендовал вам прочитать о Синхронизации контекста: https://www.codeproject.com/Articles/31971/Understanding-SynchronizationContext-Part-I

Каждая форма / диалог / usercontrol должна быть инициализирована в потоке пользовательского интерфейса, чтобы добиться этого, можно создать публичную статическую ссылку на вашу основную форму:

public static Form1 StaticReference;

Установите его в конструкторе:

public Form1()
{
     StaticReference = this;
}

Тогда в вашем коде в другом месте:

public static LogForm MyForm;
public static void AddLogLine(string inText) // is called from multiple threads
{
    <namespace>.StaticReference.BeginInvoke((MethodInvoker)delegate
    {
      if (MyForm == null) 
         MyForm = new LogForm();

      Do whatever you want with MyForm within this block.
    });
}

Любое решение, которое вы найдете, все равно должно каким-то образом распределять вызовы через поток пользовательского интерфейса.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...