TK.*_*TK. 80 c# function delay
是否有一个很好的简单方法来延迟函数调用,同时让线程继续执行?
例如
public void foo()
{
// Do stuff!
// Delayed call to bar() after x number of ms
// Do more Stuff
}
public void bar()
{
// Only execute once foo has finished
}
Run Code Online (Sandbox Code Playgroud)
我知道这可以通过使用计时器和事件处理程序来实现,但我想知道是否有一种标准的c#方式来实现这一目标?
如果有人好奇,那么需要的原因是foo()和bar()在不同的(单例)类中,我需要在特殊情况下相互调用.问题是这是在初始化时完成的,所以foo需要调用bar,它需要一个正在创建的foo类的实例...因此延迟调用bar()以确保foo完全实例化.读回来几乎是糟糕的设计!
编辑
我会在建议下接受关于糟糕设计的观点!我一直认为我可能能够改进系统,但是,这种令人讨厌的情况只会在抛出异常时发生,而在其他所有其他时候两个单身人士共存非常好.我认为我不会讨厌令人讨厌的异步模式,而是我要重构其中一个类的初始化.
Kor*_*yem 143
感谢现代C#5/6 :)
public void foo()
{
Task.Delay(1000).ContinueWith(t=> bar());
}
public void bar()
{
// do stuff
}
Run Code Online (Sandbox Code Playgroud)
dod*_*der 92
我一直在寻找类似的东西 - 我想出了以下内容,虽然它确实使用了计时器,它只使用一次初始延迟,并且不需要任何Sleep
调用......
public void foo()
{
System.Threading.Timer timer = null;
timer = new System.Threading.Timer((obj) =>
{
bar();
timer.Dispose();
},
null, 1000, System.Threading.Timeout.Infinite);
}
public void bar()
{
// do stuff
}
Run Code Online (Sandbox Code Playgroud)
(感谢Fred Deschenes关于在回调中处理计时器的想法)
cod*_*k3y 15
除了同意之前评论者的设计观察结果外,没有一个解决方案对我来说足够干净..Net 4提供了使当前线程上的延迟执行非常简单的类Dispatcher
和Task
类:
static class AsyncUtils
{
static public void DelayCall(int msec, Action fn)
{
// Grab the dispatcher from the current executing thread
Dispatcher d = Dispatcher.CurrentDispatcher;
// Tasks execute in a thread pool thread
new Task (() => {
System.Threading.Thread.Sleep (msec); // delay
// use the dispatcher to asynchronously invoke the action
// back on the original thread
d.BeginInvoke (fn);
}).Start ();
}
}
Run Code Online (Sandbox Code Playgroud)
对于上下文,我正在使用它ICommand
在UI元素上去除绑定到鼠标左键.用户双击导致各种破坏.(我知道我也可以使用Click
/ DoubleClick
处理程序,但我想要一个可以全面使用的解决方案ICommand
).
public void Execute(object parameter)
{
if (!IsDebouncing) {
IsDebouncing = true;
AsyncUtils.DelayCall (DebouncePeriodMsec, () => {
IsDebouncing = false;
});
_execute ();
}
}
Run Code Online (Sandbox Code Playgroud)
这确实是一个非常糟糕的设计,更不用说单身人士本身就是糟糕的设计.
但是,如果您确实需要延迟执行,那么您可以执行以下操作:
BackgroundWorker barInvoker = new BackgroundWorker();
barInvoker.DoWork += delegate
{
Thread.Sleep(TimeSpan.FromSeconds(1));
bar();
};
barInvoker.RunWorkerAsync();
Run Code Online (Sandbox Code Playgroud)
但是,这将bar()
在一个单独的线程上调用.如果你需要调用bar()
原始线程,你可能需要将bar()
调用移动到RunWorkerCompleted
处理程序或做一些黑客攻击SynchronizationContext
.