我有一个Windows窗体,其中包含一个列表框(Listbox1
),一个标签(label1
)和一个按钮(button1
)。我已将点击事件分配给button1
,代码如下:
public void button1_Click(object sender, EventArgs e)
{
label1.Text = "Parsing entries && initializing comms ...";
apples = new Task(Apple);
apples.Start();
Task.WaitAll(apples);
label1.Text = "No. of items: " + Listbox1.Items.Count.ToString();
if (Listbox1.Items.Count >= 2)
{
Listbox1.SetSelected(1, true);
}
}
public void Apple() {
//Send 1st command - 90000
command = "90000";
CommPort com = CommPort.Instance;
if (command.Length > 0)
{
command = ConvertEscapeSequences(command);
com.Send(command);
}
Thread.Sleep(100); //allow 100ms delay for receiving response from serial port
//Send 2nd command - 90001
command = "90001";
if (command.Length > 0)
{
command = ConvertEscapeSequences(command);
com.Send(command);
}
Thread.Sleep(100); //allow 100ms delay for receiving response from serial port
//Send 3rd command - 90002
command = "90002";
if (command.Length > 0)
{
command = ConvertEscapeSequences(command);
com.Send(command);
}
Thread.Sleep(100); //allow 100ms delay for receiving response from serial port
//Send 4th command - 90003
command = "90003";
if (command.Length > 0)
{
command = ConvertEscapeSequences(command);
com.Send(command);
}
Thread.Sleep(100); //allow 100ms delay for receiving response from serial port
//Send 5th command - 90004
command = "90004";
if (command.Length > 0)
{
command = ConvertEscapeSequences(command);
com.Send(command);
}
Thread.Sleep(100); //allow 100ms delay for receiving response from serial port
//Send 6th command - 90005
command = "90005";
if (command.Length > 0)
{
command = ConvertEscapeSequences(command);
com.Send(command);
}
Thread.Sleep(100); //allow 100ms delay for receiving response from serial port
//Listbox1 eventually contains some (~6) entries
}
但是,当我点击button1
时,label1
会显示文字No. of items: 0
,但Listbox1
确实包含6个项目。当Listbox1.Items.Count.ToString()
中实际有6个项目时,为什么代码Listbox1
会返回0?
答案 0 :(得分:1)
你不应该在诸如WaitAll
的UI线程上使用阻塞调用,因为这会导致死锁,更好的选择是使用async-await
。
有一篇关于async-await here的最佳做法的好文章。
您只能在await
mehtod中使用async
,因此您需要button1_Click
async
然后await
拨打{{1} }}。
您Apple
需要返回await
或Task
所以Task<T>
的返回值所需的方法需要更改为其中之一。您可以使用Apple
向线程池发送任何同步阻塞调用,但是必须在将在线程池上运行的Task.Run
委托之外的主线程上访问任何GUI元素。
Task.Run
如果您的串口通信api支持public async void button1_Click(object sender, EventArgs e)
{
label1.Text = "Parsing entries && initializing comms ...";
await Apple();
label1.Text = "No. of items: " + ((Listbox1.Items.Count).ToString());
if (Listbox1.Items.Count >= 2)
{
Listbox1.SetSelected(1, true);
}
}
public async Task Apple()
{
await Task.Run(()=>
{
// serial comms work ...
}
// add items to list here ...
}
,即async
,您只需SendAsync
await
次来电,并使用SendAsync
进行异步睡眠,不需要await Task.Delay(100)
。