c# – 在UI跨线程操作异常后的Task.ConfigureAwait行为
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了c# – 在UI跨线程操作异常后的Task.ConfigureAwait行为,小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含2396字,纯文字阅读大概需要4分钟。
内容图文
![c# – 在UI跨线程操作异常后的Task.ConfigureAwait行为](/upload/InfoBanner/zyjiaocheng/788/7d4ec4546ae949ba80a2ef97f7640cda.jpg)
我正在玩Task.ConfigureAwait,以便更好地理解什么是超越引擎盖.所以我在将一些UI访问内容与ConfigureAwait结合起来时遇到了这种奇怪的行为.
下面是使用简单窗体的示例应用程序,其中包含1个按钮,后跟测试结果:
private async void btnDoWork_Click(object sender, EventArgs e)
{
List<int> Results = await SomeLongRunningMethodAsync().ConfigureAwait(false);
int retry = 0;
while(retry < RETRY_COUNT)
{
try
{
// commented on test #1 & #3 and not in test #2
//if(retry == 0)
//throw new InvalidOperationException("Manually thrown Exception");
btnDoWork.Text = "Async Work Done";
Logger.Log("Control Text Changed", logDestination);
return;
}
catch(InvalidOperationException ex)
{
Logger.Log(ex.Message, logDestination);
}
retry++;
}
}
现在按钮后点击:
测试1记录结果:(正如上面的代码)
1. Cross-thread operation not valid: Control 'btnDoWork' accessed from a thread other than the thread it was created on.
2. Control Text Changed
测试2日志结果:(手动例外抛出未注释)
1. Manually thrown Exception
2. Cross-thread operation not valid: Control 'btnDoWork' accessed from a thread other than the thread it was created on.
3. Control Text Changed
测试3日志结果:(与1相同,但没有调试器)
1. Control Text Changed
所以问题是:
>为什么第一个UI访问(跨线程
操作)在Main上执行循环的下一次迭代
线程?
>为什么手动异常不会导致相同的行为?
>为什么在没有附加调试器的情况下执行上面的示例(直接来自exe)
不表现出相同的行为?
解决方法:
这个让我挠了一下头,但终于找到了诀窍.
Button.Text属性的setter代码是:
set
{
if (value == null)
value = "";
if (value == this.Text)
return;
if (this.CacheTextInternal)
this.text = value;
this.WindowText = value;
this.OnTextChanged(EventArgs.Empty);
if (!this.IsMnemonicsListenerAxSourced)
return;
for (Control control = this; control != null; control = control.ParentInternal)
{
Control.ActiveXImpl activeXimpl = (Control.ActiveXImpl) control.Properties.GetObject(Control.PropActiveXImpl);
if (activeXimpl != null)
{
activeXimpl.UpdateAccelTable();
break;
}
}
}
抛出异常的行是this.WindowText = value; (因为它在内部尝试访问按钮的Handle属性).诀窍是,就在之前,它在某种缓存中设置text属性:
if (this.CacheTextInternal)
this.text = value;
我会说实话,我不知道这个缓存是如何工作的,或者它是否被激活(事实证明,它似乎在这个精确的情况下被激活).但正因为如此,即使抛出异常,也会设置文本.
在循环的进一步迭代中,没有任何反应,因为该属性有一个特殊的检查,以确保您没有设置两次相同的文本:
if (value == this.Text)
return;
如果您每次都更改循环以设置不同的文本,那么您将看到在每次迭代时都会一致地抛出异常.
内容总结
以上是互联网集市为您收集整理的c# – 在UI跨线程操作异常后的Task.ConfigureAwait行为全部内容,希望文章能够帮你解决c# – 在UI跨线程操作异常后的Task.ConfigureAwait行为所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。