无法将 匿名方法 转换为类型“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).点击详细内容:有关调用实 ...
随机推荐
- Android 项目中文件夹的说明与作用(转)
(转自:http://blog.csdn.net/goodshot/article/details/11529731) Android 项目中文件夹的作用 1. src:存放所有的*.java源程序. ...
- RabbitMQ与Redis队列对比
本文仅针对RabbitMQ与Redis做队列应用时的情况进行对比具体采用什么方式实现,还需要取决于系统的实际需求 简要介绍 RabbitMQ RabbitMQ是实现AMQP(高级消息队列协议)的消息中 ...
- 报表引擎API开发入门—带参程序数据集
我们今天又来讲讲报表开发的事,上周开的这个系列入门文章也三四天了,浏览量不佳小编甚是悲伤啊,希望大家多多支持我! 一.问题描述 在实际应用中,可能需要根据表名动态地改变数据源,比如在程序数据集中,通过 ...
- C++浅析——继承类中构造和析构顺序
先看测试代码,CTEST 继承自CBase,并包含一个CMember成员对象: static int nIndex = 1; class CMember { public: CMember() { p ...
- js生成[n,m]的随机数
一.预备知识 Math.ceil(); //向上取整. Math.floor(); //向下取整. Math.round(); //四舍五入. Math.random(); //0.0 ~ 1 ...
- Java Web之Filter
Filter被称为过滤器或者拦截器,基本功能就是对调用servler过程的拦截,在servlet进行响应和处理前后实现一些特殊功能.其实,Filter过滤器就是一个实现了javax.servlet.F ...
- ArrayList实现线程安全的blogs
ArrayList是线程不安全的,轻量级的.如何使ArrayList线程安全? 1.继承Arraylist,然后重写或按需求编写自己的方法,这些方法要写成synchronized,在这些synchro ...
- DOM、Window操作
一.DOM的基本概念 DOM是文档对象模型,这种模型为树模型:文档是指标签文档:对象是指文档中每个元素:模型是指抽象化的东西. 一.基本语法: 数据类型(字符串,小数,整数,布尔,时间) var, v ...
- Java之线程处理之二
No.1编写一个打印机类 写两个方法 public class Printer { public void print1() { System.out.print("微"); Sy ...
- 任务调度开源框架Quartz动态添加、修改和删除定时任务
Quartz 是个开源的作业调度框架,为在 Java 应用程序中进行作业调度提供了简单却强大的机制.Quartz框架包含了调度器监听.作业和触发器监听.你可以配置作业和触发器监听为全局监听或者是特定于 ...