Операция перекрестного потока, не допустимая при слушании COM-порта [дубликат]

потому что Вы не связываете свой код с конкретной реализацией списка some_vector. при использовании индексов массива это должна быть некоторая форма массива; при использовании итераторов, можно использовать тот код любой реализации списка.

7
задан Community 23 May 2017 в 12:30
поделиться

2 ответа

Я предполагаю, что MyDataReceivedHandler работает в другом потоке, чем графический интерфейс. Чтобы исправить это, вам необходимо вызвать установщики Text в правильном потоке. Это пример этого:

public void SetControlText(Control control, string text)
{
    if (this.InvokeRequired)
    {
        this.Invoke(new Action<Control,string>(SetControlText), new object[] { control, text });
    }
    else
    {
        control.Text = text;
    }
}

private void MyDataReceivedHandler(object sender, SerialDataReceivedEventArgs e)
{
    try
    {
        //sp.PortName = "COM3";
        //sp.Open();
        SetControlText(Label1, sp.ReadLine());
    }
    catch (Exception exception)
    {
        SetControlText(RichTextBox1, exception.Message + "\n\n" + exception.Data);
    }
    finally
    {
        sp.Close();
    }
}

Если вы используете .NET Framework 2.0, указанный выше делегат Action недоступен, поэтому вам придется определить свой собственный:

private delegate void SetControlTextHandler(Control control, string text);

public void SetControlText(Control control, string text)
{
    if (this.InvokeRequired)
    {
        this.Invoke(new SetControlTextHandler(SetControlText), new object[] { control, text });
    }
    else
    {
        control.Text = text;
    }
}

Метод SetControlText можно сделать короче (и даже статическим) следующим образом (это работает как в 2.0, так и в 3.5):

public static void SetControlText(Control control, string text)
{
    ´control.Invoke((MethodInvoker)delegate { control.Text = text; });
}

Тогда вам не нужно выполнять проверку InvokeRequired каждый раз, но вы, с другой стороны, заключите вызов в делегат, даже если он не нужен. Я думаю, что в таком методе графического интерфейса, как этот, любой разницей в производительности между этими двумя нельзя пренебречь, поэтому я предпочитаю использовать более короткую форму,

19
ответ дан 6 December 2019 в 09:20
поделиться

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

(. NET 3.5)

myControl.BeginInvoke(new MethodInvoker( () => myControl.whatever = whatever; ));

или (.NET 2.0)

myControl.BeginInvoke(new MethodInvoker( delegate { myControl.whatever = whatever; ));

edit> Иногда использование Invoke для длительной операции может / все еще может привести к зависанию пользовательского интерфейса, использование BeginInvoke, очевидно, выполняет эту операцию асинхронно, и пользовательский интерфейс не зависает.

1
ответ дан 6 December 2019 в 09:20
поделиться
Другие вопросы по тегам:

Похожие вопросы: