无法将 匿名方法 转换为类型“System.Delegate”,因为它不是委托类型:解决方法
http://blog.csdn.net/xiaochongchong1248/archive/2009/11/20/4841193.aspx?1271573283
编程环境要求:VS2008/FX2.0
众所周知,从VS2005/FX2.0起,在多线程环境下是不允许跨线程修改主线程上窗口控件的。
例如:

private void button1_Click(object sender, EventArgs e)
{
Thread t = new Thread(new ThreadStart(CrossThreadCall));
t.Start();
}
public void CrossThreadCall()
{
Text = "test";
}

将直接导致异常:
未处理 System.InvalidOperationException
Message="线程间操作无效: 从不是创建控件“Form1”的线程访问它。"
Source="System.Windows.Forms"
StackTrace:
在 System.Windows.Forms.Control.get_Handle()
在 System.Windows.Forms.Control.set_WindowText(String value)
在 System.Windows.Forms.Form.set_WindowText(String value)
在 System.Windows.Forms.Control.set_Text(String value)
在 System.Windows.Forms.Form.set_Text(String value)
在 delegate_test1.Form1.CrossThreadCall() 位置 f:\app\delegate_test1\delegate_test1\Form1.cs:行号 26
在 System.Threading.ThreadHelper.ThreadStart_Context(Object state)
在 System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
在 System.Threading.ThreadHelper.ThreadStart()
通用的解决方法是使用Control.Invoke方法来调用一个Delegate,从而安全地跨线程调用。
例如:

public void CrossThreadCall()
{
Invoke(new void_d(CrossThreadCall_Local));
}
void CrossThreadCall_Local()
{
Text = "test";
}
public delegate void void_d();

但是这样的缺点是要不得不为每个调用编写一个Invoke跳板,还要额外声明一个委托类型,实在不怎么优雅。
于是我们想到用匿名函数来写。我的第一反应是:
可惜不行。编译压根就没通过,写着:
无法将 匿名方法 转换为类型“System.Delegate”,因为它不是委托类型
无语,delegate竟然不是委托类型?
等我把Google翻了一遍后,找到了答案。
The problem the user is seeing is that the Thread ctor accepts a specific delegate -- the ThreadStart delegate. The C# compiler will check and make sure your anonymous method matches the signature
of the ThreadStart delegate and, if so, produces the proper code under-the-covers to create the ThreadStart delegate for you.
But Control.Invoke is typed as accepting a "Delegate". This means it can accept any delegate-derived type. The example above shows an anonymous method that has a void return type and takes no parameters.
It's possible to have a number of delegate-derived types that match that signature (such as MethodInvoker and ThreadStart -- just as an example). Which specific delegate should the C# compiler use? There's no way for it to infer the exact delegate type so
the compiler complains with an error.
也就是说,对于Thread.ctor()来说,由于接受的是一个ThreadStart委托,编译器便可以将匿名函数与ThreadStart委托类型匹配,最后能够正确编译。
而对于Control.Invoke()来说,任何的代理类型都是可接受的,也就是说ThreadStart和MethodInvoker都是可以接受的类型。这样编译器反而不知道应该用哪个代理去匹配匿名函数了,导致了编译错误的发生。
知道了原因,问题就很容易解决了。我们只需要加上MethodInvoker这个wrapper就能使用匿名函数了。
或者更简单地,用Lambda表达式来解决问题:
希望本文能够帮助有同样困惑的朋友。
出处: http://yelaiju.cnblogs.com
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
无法将 匿名方法 转换为类型“System.Delegate”,因为它不是委托类型:解决方法的更多相关文章
- 关于委托:异常{ 无法将 匿名方法 转换为类型“System.Delegate”,因为它不是委托类型 }
转自:http://www.cnblogs.com/xiaofei59/archive/2010/11/25/1887285.html 异常{ 无法将 匿名方法 转换为类型“System.Delega ...
- 关于委托:异常{ 无法将 匿名方法 转换为类型“System.Delegate”,因为它不是委托类型 }
异常{ 无法将 匿名方法 转换为类型"System.Delegate",因为它不是委托类型 } 委托实际上是把方法名作为参数,但是若有好多个方法时,就要指明是哪个参数 查看如下代 ...
- 无法将 lambda 表达式 转换为类型“System.Delegate”,因为它不是委托类型
今天写winform的时候遇到一个问题,提示: 无法将 lambda 表达式 转换为类型“System.Delegate”,因为它不是委托类型, 主要是为了在子线程中更新UI线程,在wpf中同样的写法 ...
- 无法读取配置节 system.serviceModel 因为它缺少节声明的解决方法
无法读取配置节 system.serviceModel 因为它缺少节声明的解决方法,需要的朋友可以参考下 在Windows Server2008 R2中的IIS7中部署WCF服务时报出如题错误: HT ...
- MaterialDesignInXamlToolkit“无法绑定到目标方法,因其签名或安全透明度与委托类型的签名或安全透明度不兼容”异常的解决思路
前言: 最初是想解答园友"小代码大世界 "的问题,后来想举一反三,将这个问题简单剖析下,做到知其所以然. MaterialDesignInXAML 控件库高度封装,有一些控件在使用 ...
- System.Data.OleDb.OleDbException: 未指定的错误的解决方法
异常详细信息: System.Data.OleDb.OleDbException: 未指定的错误 这个错误是access数据库特有的错误,当access频繁读取或操作过多的时候就会发生这个错误,微软官 ...
- "System.Security.Cryptography.CryptographicException: 拒绝访问" 问题的解决方法
.net web程序使用rsa算法进行加解密时,程序报告“System.Security.Cryptography.CryptographicException: 拒绝访问”错.按网上搜的解决方法做了 ...
- 异常详细信息: System.Web.Hosting.HostingEnvironmentException: 访问 IIS 元数据库失败 解决方法
访问IIS元数据库失败 同理,给操作系统的新建用户赋予IIS操作权限同样可以采用该命令来处理 说明: 执行当前 Web 请求期间,出现未处理的异常.请检查堆栈跟踪信息,以了解有关该错误以及代码中导致错 ...
- “System.Runtime.InteropServices.COMException (0x80070422): 无法启动服务”解决方法
应用程序中发生了无法处理的异常.如果单击“退出”,应用程序将立即关闭.无法启动服务,原因可能是已被禁用或其相关联设备没有启动.(异常来自HRESULT:0X80070422).点击详细内容:有关调用实 ...
随机推荐
- TCP连接建立系列 — 服务端接收ACK段(一)
http://blog.csdn.net/zhangskd/article/details/17923917 分类: Linux TCP/IP Linux Kernel 2014-01-07 09 ...
- VS2010最常用快捷键
1.选择类 F8 当前位置变成选定区域的头/尾(再移动光标或者点鼠标就会选定) Ctrl + F8 当前行变成选定区域的头/尾(再移动上下光标或者点鼠标就会选定多行) CTRL + W 选择当前单词 ...
- Hadoop_MapReduce流程
Hadoop学习笔记总结 01. MapReduce 1. Combiner(规约) Combiner号称本地的Reduce. 问:为什么使用Combiner? 答:Combiner发生在Map端,对 ...
- pyenv 使用简介
pyenv 是一个 python 版本管理工具,可以方便用户在不同的 python 版本间切换,例如我的电脑里默认的 python 是 2.6, 但我还想装 2.7 3.5 等.另有一个名为 pyen ...
- Unity3D FPS帧数修改
修改Unity的FPS FPS是游戏运行的帧数,本文讲解如何修改Unity引擎的FPS. 步骤 1.在 Edit/Project Settings/Quality 质量设置里把帧数设定关闭,关闭之后 ...
- pitch yaw roll 的区别
http://blog.163.com/vipwdp@126/blog/static/150224366201281935518196/
- 隐写-CTF中图片隐藏文件分离方法总结
0x00 前言 在安全的大趋势下,信息安全越来越来受到国家和企业的重视,所以CTF比赛场次越来越多,而且比赛形式也不断的创新,题目也更加新颖有趣,对选手的综合信息安全能力有一个较好的考验,当然更好的是 ...
- ajax asud模板
<table class="table"> <tr> <th>@Html.DisplayNameFor(model=>model.Id)& ...
- MySQL导入sql脚本错误:2006 - MySQL server has gone away
到如一些小脚本很少报错,但最近导入一个10+M的SQL脚本,却重复报错: Error occured at:2014-03-24 11:42:24 Line no.:85 Error Code: 20 ...
- Linux中 groupadd 和 useradd 的命令说明
groupadd [options] group 说明The groupadd command creates a new group account using the values specifi ...