Не возвращаются данные через задачу из последовательного порта

У меня вопрос по задачам. Я хочу открыть новую задачу и запустить метод.

public void runProgram(CancellationToken token)
{
    Task t1 = Task.Run(() => 
    {
        Task task1 = Task.Factory.StartNew(method1, token);
        //task 2 Just open a loading Dialog with a cancel button
        Task task2 = Task.Factory.StartNew(method2, token);
        Task.WaitAll(task1, task2);
    }, token);
}

а кнопка отмены просто отменяет задачу. Это работает нормально, но в методе 1 я читаю данные с помощью data = _MainForm.serialPort.ReadExisting();, если я запускаю метод без задачи, все работает нормально, но если я запускаю его с задачей, я не получаю никаких данных. Но мне нужна задача, если я хочу отменить выполнение... Что я могу там сделать?

Если я запускаю его так, он также не работает. Любые идеи? Должен ли я дать задаче какие-то объекты из Mainform или что-то в этом роде?

Task t1 = Task.Run(() => 
{
    method1();
}, token);

person Patrick Schies    schedule 28.11.2017    source источник


Ответы (2)


Выполнение каких-либо действий в контексте задачи изменяет ряд вещей, о которых вы можете не знать. Посмотрите, когда вы используете Task.Run, ваш код выполняется асинхронно в другом потоке, и если вы пытаетесь взаимодействовать с пользовательским интерфейсом из этого потока, он можно вызвать исключение «Межпоточная операция недействительна», что приведет к поведению, свидетелем которого вы были.

Допустим, у вас есть текстовое поле с именем textBox1, которое вы меняете после завершения метода 1. Если вы просто назначаете текст, например textBox1.Text = "hello", вы, скорее всего, получите исключение, вместо этого вы должны попробовать что-то вроде этого:

public void updateTextBox(string newText)
{
    if (this.InvokeRequired)
    {
        this.BeginInvoke((Action<string>)updateTextBox, newText);
        return;
    }
    textBox1.Text = newText;
}

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

public void updateTextBox(string newText)
{
    if (!Dispatcher.CheckAccess())
    {
        Dispatcher.BeginInvoke((Action<string>)updateTextBox, newText);
        return;
    }
    textBox1.Text = newText;
}

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

Кода

person Kodaloid    schedule 28.11.2017
comment
Вы, наверное, представляете? У меня все еще есть эта проблема, если я использую this.Invoke((MethodInvoker)delegate { method2(); }); - person Patrick Schies; 01.12.2017

Это много кода, я думаю, что это слишком много. Надеюсь, я смогу это описать. Method1, вызывающий другие методы в той последовательности, в которой пользователь хочет их вызвать.

public void method1(){
    switch(sequence){
        case 1:
            method2();
            break;
        case 2:
            method3();
            break;
    }

как это и так далее .... и в методе2 я выполняю свой код.

public void method2(int function){
    //Heres some code like:
    datas = helpfunction(function);
    portarray[1] = adress;    
    portarray[2] = datas;    
    _MainForm.serialPort.Write(portarray, 0, 4);
    data = _MainForm.serialPortPrüfling.ReadExisting();
    if(data != stringexample)
    {
        string ex = "Error";
        catch_exeption(null, ex);
        return;
    }
}

Я добавил это в свой код в начале:

if (this.InvokeRequired)
{
    this.BeginInvoke((Action<int>)method2, function);
    return;
}

Означает ли это, что правильный поток выполняет мою функцию сейчас??? Я новичок в этой теме, извините :(

person Patrick Schies    schedule 28.11.2017