xyz*_*xyz 120 c# lambda delegates c#-3.0
采取方法System.Windows.Forms.Control.Invoke(Delegate方法)
为什么会出现编译时错误:
string str = "woop";
Invoke(() => this.Text = str);
// Error: Cannot convert lambda expression to type 'System.Delegate'
// because it is not a delegate type
Run Code Online (Sandbox Code Playgroud)
但这很好用:
string str = "woop";
Invoke((Action)(() => this.Text = str));
Run Code Online (Sandbox Code Playgroud)
当方法需要普通代表时?
Jon*_*eet 122
lambda表达式可以转换为委托类型或表达式树 - 但它必须知道哪个委托类型.只知道签名是不够的.例如,假设我有:
public delegate void Action1();
public delegate void Action2();
...
Delegate x = () => Console.WriteLine("hi");
Run Code Online (Sandbox Code Playgroud)
您期望所提及的对象的具体类型x是什么?是的,编译器可以生成具有适当签名的新委托类型,但这很少有用,并且最终减少了错误检查的机会.
如果您希望通过最简单的方法轻松调用Control.Invoke,Action请向Control添加扩展方法:
public static void Invoke(this Control control, Action action)
{
control.Invoke((Delegate) action);
}
Run Code Online (Sandbox Code Playgroud)
小智 33
厌倦了一遍又一遍地抛弃lambda?
public sealed class Lambda<T>
{
public static Func<T, T> Cast = x => x;
}
public class Example
{
public void Run()
{
// Declare
var c = Lambda<Func<int, string>>.Cast;
// Use
var f1 = c(x => x.ToString());
var f2 = c(x => "Hello!");
var f3 = c(x => (x + x).ToString());
}
}
Run Code Online (Sandbox Code Playgroud)
Pet*_*one 12
人们得到这个的时间只有十分之九,因为他们正试图编组到UI线程上.这是懒惰的方式:
static void UI(Action action)
{
System.Windows.Threading.Dispatcher.CurrentDispatcher.BeginInvoke(action);
}
Run Code Online (Sandbox Code Playgroud)
现在它被打字了,问题消失了(qv Skeet's anwer),我们有这个非常简洁的语法:
int foo = 5;
public void SomeMethod()
{
var bar = "a string";
UI(() =>
{
//lifting is marvellous, anything in scope where the lambda
//expression is defined is available to the asynch code
someTextBlock.Text = string.Format("{0} = {1}", foo, bar);
});
}
Run Code Online (Sandbox Code Playgroud)
对于奖励积分,这是另一个提示.您不会为UI内容执行此操作,但在需要SomeMethod阻塞直到完成(例如请求/响应I/O,等待响应)的情况下,请使用WaitHandle(qv msdn WaitAll,WaitAny,WaitOne).
请注意,AutoResetEvent是WaitHandle派生物.
public void BlockingMethod()
{
AutoResetEvent are = new AutoResetEvent(false);
ThreadPool.QueueUserWorkItem ((state) =>
{
//do asynch stuff
are.Set();
});
are.WaitOne(); //don't exit till asynch stuff finishes
}
Run Code Online (Sandbox Code Playgroud)
最后的提示是因为事情会变得纠结:WaitHandles会阻止线程.这是他们应该做的.如果您在停止时尝试编组UI线程,您的应用程序将挂起.在这种情况下(a)一些严重的重构是有序的,并且(b)作为临时黑客你可以这样等待:
bool wait = true;
ThreadPool.QueueUserWorkItem ((state) =>
{
//do asynch stuff
wait = false;
});
while (wait) Thread.Sleep(100);
Run Code Online (Sandbox Code Playgroud)