C # как использовать async и ждать? - PullRequest
0 голосов
/ 14 июня 2019

Я делаю последовательный метод связи.сначала возвращается сообщение о получении

, нажатие кнопки

List<string> SendPkt = new List<string>();
List<string> RecvPkt = new List<string>();

private void btnRead_Click(object sender, EventArgs e)
{
    SendPkt.Clear();
    RecvPkt.Clear();

    C_Serial c_serial = new C_Serial();

    Trace.WriteLine("start : "+DateTime.Now);

    RecvPkt = c_serial.CommunicationJob(Port, Baud, SendPkt);

    for (int i = 0; i < RecvPkt.Count; i++)
        Trace.WriteLine(RecvPkt[i]);

    Trace.WriteLine("end : "+DateTime.Now);
}

и C_Serial is ...

public List<string> CommunicationJob(string port, int boud, List<string> sendPkt)
{
    string openResult = OpenPort(port, boud);
    string recvMsg = "";
    ....
    List<string> recvs = new List<string>();

    for (int i = 0; i < sendPkt.Count; i++)
    {
        recvMsg = SendAndRecv(sendPkt[i]);
        Trace.WriteLine("recvMsg : " + recvMsg);
        recvs.Add(recvMsg);
    }

    return recvs;
}
...
public string SendAndRecv(string sendPkt)
{
    string recvPkt = "";
    serialWrite(sendPkt);
    recvPkt = waitDataReceived();
    return recvPkt;
}

...

private string waitDataReceived()
{
    while(true)
    {
        // check about message recv complete
    }
}

waitDataReceived () имеет цикл бесконечности, поэтому он должен работать как поток

Так что я делаю SendAndRecv () вот так

public string SendAndRecv(string sendPkt)
{
    string recvPkt = "";
    serialWrite(sendPkt);
    Thread th = new Thread(() => recvPkt = waitDataReceived());
    th.Start();
    th.Join();
    return recvPkt;
}

, но Join () - это блочный интерфейс при бесконечном цикле.

Я ищу это и нахожу async / await.

Поэтому я изменил SendAndRecv ()

public async Task<string> SendAndRecv(string sendPkt)
{
    string recvs = "";
    serialWrite(sendPkt);   
    recvs = await Task.Run(() => waitDataReceived());
    return recvs;
}

И он используется в CommunicationJob () следующим образом

recvMsg = SendAndRecv(sendPkt[i]).Result;

Но он все еще блокирует пользовательский интерфейс.Даже если бесконечный цикл прерывается, он не освобождается.

И не печатайте recvMsg в CommunicationJob ().

Программа остановлена.

Как использовать потокне блокировать пользовательский интерфейс и дождаться возврата значения?

Ответы [ 2 ]

2 голосов
/ 14 июня 2019

вам нужно увеличить шаблон до тех пор, пока ваш метод щелчка GUI.В строке последовательности (иерархия вызовов) каждый метод должен быть асинхронным и использовать await

public async Task<List<string>> CommunicationJob(string port, int boud, List<string> sendPkt)
{
    string openResult = OpenPort(port, boud);
    string recvMsg = "";
    ....
    List<string> recvs = new List<string>();

    for (int i = 0; i < sendPkt.Count; i++)
    {
        recvMsg = await SendAndRecv(sendPkt[i]);
        Trace.WriteLine("recvMsg : " + recvMsg);
        recvs.Add(recvMsg);
    }

    return recvs;
}

private async void btnRead_Click(object sender, EventArgs e)
{
    SendPkt.Clear();
    RecvPkt.Clear();

    C_Serial c_serial = new C_Serial();

    Trace.WriteLine("start : "+DateTime.Now);

    RecvPkt = await c_serial.CommunicationJob(Port, Baud, SendPkt);

    for (int i = 0; i < RecvPkt.Count; i++)
        Trace.WriteLine(RecvPkt[i]);

    Trace.WriteLine("end : "+DateTime.Now);
}

Это должно гарантировать, что пользовательский интерфейс не зависает.

Youможет на самом деле написать ожидание сразу после оператора return:

public async Task<string> SendAndRecv(string sendPkt)
{
    string recvs = "";
    serialWrite(sendPkt);
    return await Task.Run(() => waitDataReceived());;
}
1 голос
/ 14 июня 2019

Мало того, что вы должны сделать SendAndRecv асинхронным, вы также должны сделать все его вызывающие и вызывающие из этих вызывающих (и так далее) async.И когда вы вызываете метод async, вы используете await.

Следовательно, CommunicationJob должно быть async

public async Task<List<string>> CommunicationJob(string port, int boud, List<string> sendPkt)
{
    string openResult = OpenPort(port, boud);
    string recvMsg = "";
    ....
    List<string> recvs = new List<string>();

    for (int i = 0; i < sendPkt.Count; i++)
    {
        recvMsg = await SendAndRecv(sendPkt[i]); // <--- note this line!
        Trace.WriteLine("recvMsg : " + recvMsg);
        recvs.Add(recvMsg);
    }

    return recvs;
}

И btnRead_Click должно быть async

private async void btnRead_Click(object sender, EventArgs e)
{
    SendPkt.Clear();
    RecvPkt.Clear();

    C_Serial c_serial = new C_Serial();

    Trace.WriteLine("start : "+DateTime.Now);

    RecvPkt = await c_serial.CommunicationJob(Port, Baud, SendPkt);

    for (int i = 0; i < RecvPkt.Count; i++)
        Trace.WriteLine(RecvPkt[i]);

    Trace.WriteLine("end : "+DateTime.Now);
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...