【发布时间】:2017-11-28 14:42:51
【问题描述】:
在这个问题中,我提供了一些链接,这些链接表明我已经完成了一些工作来寻找解决方案。
我正在开发一个带有触摸屏和 GPIO 的 UWP 应用。
UI 有一个停止按钮、一个重置按钮和一个文本块。 GPIO 用于一个物理启动按钮、一个电机和 2 个限位开关。电机可以旋转直到碰到限位开关。
控制硬件的代码(例如,Motor.Forward())已经编写和测试,但为简洁起见,本问题不包括在内。出于同样的原因,停止按钮的代码被排除在外。
如果这些方法中的步骤将同步执行...所需的行为可能由以下代码描述:
//Event handler for when physical start button is pushed
private async void StartButtonPin_ValueChanged(GpioPin sender, GpioPinValueChangedEventArgs args)
{
Start();
}
private void Start()
{
//Update UI
stopButton.IsEnabled = true;
resetButton.IsEnabled = false;
textBlock.Text = "Motor turning";
Motor.Forward();
while(Motor.HasNotHitEndLimit())
Motor.Off();
//Update UI
stopButton.IsEnabled = false;
resetButton.IsEnabled = true;
textBlock.Text = "Task complete";
}
//Event handler for reset button
private void btnReset_Click()
{
//Update UI
stopButton.IsEnabled = true;
resetButton.IsEnabled = false;
textBlock.Text = "Motor turning";
Motor.Back();
while(Motor.HasNotHitStartLimit())
Motor.Off();
//Update UI
stopButton.IsEnabled = false;
resetButton.IsEnabled = true;
textBlock.Text = "Reset complete";
}
如果我没记错的话,“private void btnReset_Click()”中的 UI 更新可以工作,但它们不是同步的……也就是说,所有 UI 更新都在“btnReset_Click()”完成后立即完成。
From reading answers to similar questions... 似乎“Start()”中的 UI 更新失败,因为我不在 UI 线程上(“应用程序调用了一个为不同线程编组的接口。”)。 似乎任务异步模式是这类问题的常见答案。然而,我这样做的尝试产生了奇怪的结果......
下面的代码是我最接近预期结果的代码。我添加了使用 CoreDispatcher 处理 UI 更新的异步任务。
//Task for updating the textblock in the UI
private async Task UpdateText(string updateText)
{
await Dispatcher.RunAsync(CoreDispatcherPriority.Normal,
new DispatchedHandler(() => { textBlock.Text = updateText; }));
}
//Task for enable/disable a given button
private async Task UpdateButton(Button btn, bool shouldThisBeEnabled)
{
await Dispatcher.RunAsync(CoreDispatcherPriority.Normal,
new DispatchedHandler(() => { btn.IsEnabled = shouldThisBeEnabled; }));
}
//Event handler for when physical start button is pushed
private async void StartButtonPin_ValueChanged(GpioPin sender, GpioPinValueChangedEventArgs args)
{
Start();
}
private void Start()
{
//Update UI
UpdateButton(stopButton,true).Wait();
UpdateButton(resetButton,false).Wait();
UpdateText("Motor turning").Wait();
Motor.Forward();
while(Motor.HasNotHitEndLimit())
Task.Delay(1).Wait();
Motor.Off();
//Update UI
UpdateButton(stopButton,false).Wait();
UpdateButton(resetButton,true).Wait();
UpdateText("Task complete").Wait();
}
//Event handler for reset button
private async void btnReset_Click()
{
//Update UI
await UpdateButton(stopButton,true);
await UpdateButton(resetButton,false);
await UpdateText("Motor turning");
await Task.Delay(1);
Motor.Back();
while(Motor.HasNotHitStartLimit())
await Task.Delay(1);
Motor.Off();
//Update UI
await UpdateButton(stopButton,false);
await UpdateButton(resetButton,true);
await UpdateText("Reset complete");
}
上面代码的问题/特性(除了我可能因为刚开始使用 C# 而犯的任何初学者错误......以及它似乎过于复杂和令人困惑的事实):
-在“Start()”中,我在任务上使用 .Wait()(因为它似乎有效,我真的不明白为什么......),在 btnReset_Click() 中等待它们效果最好。 ..
-btnReset_Click() 不是同步的。 UI 更新似乎“落后了一步”......即,在调试模式下,当我跨过“await UpdateButton(resetButton,false)”时,停止按钮启用,当我跨过“await UpdateText(”Motor) 时,重置按钮禁用转动")"等等。
-关于 btnReset_Click()... while 循环实时持续时间超过 1 毫秒,但如果我删除所有“等待 Task.Delay(1)”,则 UI 更新将“落后一步”。包含“await Task.Delay(1)”后,UI 更新会“赶上”到应有的位置。为什么“await Task.Delay(1)”会以这种方式影响 UI 更新?
如果有知识渊博的人愿意解决这个问题的部分/全部,也许让我向他们询问有关他们答案的详细信息,我将不胜感激!
额外问题....我在触摸屏上还有一个“切换测试模式”按钮,它启用一个 UI 按钮列表并禁用另一个(基于静态布尔“testmode”)。 I don't need to use TAP to update the UI here,但请记住我想同步执行此操作(即使在此示例中似乎毫无意义)。
private async void btnTestMode_Click(object sender, RoutedEventArgs e)
{
testMode = !testMode;
if (testMode == true)
{
await UpdateButtons(TestModeButtons,true);
await UpdateButtons(NormalModeButtons,false);
return;
}
await UpdateButtons(TestModeButtons,true);
await UpdateButtons(NormalModeButtons,false);
}
private async Task UpdateButtons(List<Button> btns, enable)
{
foreach (var btn in btns)
{
await Dispatcher.RunAsync(CoreDispatcherPriority.Normal,
new DispatchedHandler(() => { btn.IsEnabled = enable; }));
}
}
正如上面所写,它的行为类似于 btnReset_Click()...,其中 UI 更新“落后了一步”。但是,如果我在事件处理程序中的每个等待中添加“.ConfigureAwait(false)”,那么它就会变成同步的。 I've done some reading on this topic, but don't fully understand it yet,我希望有更好理解的人来帮助我理解它,因为它与我的项目有关。
【问题讨论】:
标签: c# xaml asynchronous uwp async-await