C# 延迟函数调用

C# 延迟函数调用,c#,function,delay,C#,Function,Delay,有没有一种简单的方法可以延迟函数调用,同时让线程继续执行 e、 g 我知道这可以通过使用计时器和事件处理程序来实现,但我想知道是否有一种标准的c#方式来实现这一点 如果有人好奇的话,需要这样做的原因是foo()和bar()在不同的(单例)类中,我需要在特殊情况下相互调用它们。问题是这是在初始化时完成的,所以foo需要调用bar,它需要一个正在创建的foo类的实例。。。因此,延迟了对bar()的调用,以确保foo完全实例化。。读这本书几乎有点糟糕的设计 编辑 我会考虑一下关于糟糕设计的观点!我一直

有没有一种简单的方法可以延迟函数调用,同时让线程继续执行

e、 g

我知道这可以通过使用计时器和事件处理程序来实现,但我想知道是否有一种标准的c#方式来实现这一点

如果有人好奇的话,需要这样做的原因是foo()和bar()在不同的(单例)类中,我需要在特殊情况下相互调用它们。问题是这是在初始化时完成的,所以foo需要调用bar,它需要一个正在创建的foo类的实例。。。因此,延迟了对bar()的调用,以确保foo完全实例化。。读这本书几乎有点糟糕的设计

编辑


我会考虑一下关于糟糕设计的观点!我一直认为我可能能够改进系统,然而,这种糟糕的情况只有在抛出异常时才会发生,在其他任何时候,这两个单例都可以很好地共存。我想我不会去胡乱处理讨厌的异步模式,而是要重构其中一个类的初始化。

这听起来像是对这两个对象的创建及其相互依赖性的控制需要外部控制,而不是在类之间控制。

嗯,我必须同意“设计”的观点。。。但是你可以用监视器让一个知道另一个什么时候通过了临界区

    public void foo() {
        // Do stuff!

        object syncLock = new object();
        lock (syncLock) {
            // Delayed call to bar() after x number of ms
            ThreadPool.QueueUserWorkItem(delegate {
                lock(syncLock) {
                    bar();
                }
            });

            // Do more Stuff
        } 
        // lock now released, bar can begin            
    }

除了使用计时器和事件,没有标准的方法来延迟对函数的调用


这听起来像是GUI的反模式,延迟对方法的调用,以便确保表单已经完成布局。这不是一个好主意。

这的确是一个非常糟糕的设计,更不用说单例本身就是糟糕的设计了

但是,如果您确实需要延迟执行,您可以这样做:

BackgroundWorker barInvoker = new BackgroundWorker();
barInvoker.DoWork += delegate
    {
        Thread.Sleep(TimeSpan.FromSeconds(1));
        bar();
    };
barInvoker.RunWorkerAsync();

但是,这将在单独的线程上调用
bar()
。如果您需要在原始线程中调用
bar()
,您可能需要将
bar()
调用移动到
RunWorkerCompleted
处理程序,或者使用
SynchronizationContext

进行一些黑客攻击,我自己也在寻找类似的东西-我提出了以下内容,尽管它使用了计时器,它只在初始延迟中使用它一次,并且不需要任何
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
}

(感谢在回调中处理计时器的想法)

我认为最好的解决方案是让计时器处理延迟的操作。 FxCop不喜欢间隔小于一秒的情况。 我需要将操作延迟到DataGrid完成按列排序之后。 我想一个一次性计时器(AutoReset=false)将是解决方案,它工作得非常完美。
而且,FxCop不会让我取消警告

根据David O'Donoghue的回答,这里是延迟代表的优化版本:

using System.Windows.Forms;
using System.Collections.Generic;
using System;

namespace MyTool
{
    public class DelayedDelegate
    {
       static private DelayedDelegate _instance = null;

        private Timer _runDelegates = null;

        private Dictionary<MethodInvoker, DateTime> _delayedDelegates = new Dictionary<MethodInvoker, DateTime>();

        public DelayedDelegate()
        {
        }

        static private DelayedDelegate Instance
        {
            get
            {
                if (_instance == null)
                {
                    _instance = new DelayedDelegate();
                }

                return _instance;
            }
        }

        public static void Add(MethodInvoker pMethod, int pDelay)
        {
            Instance.AddNewDelegate(pMethod, pDelay * 1000);
        }

        public static void AddMilliseconds(MethodInvoker pMethod, int pDelay)
        {
            Instance.AddNewDelegate(pMethod, pDelay);
        }

        private void AddNewDelegate(MethodInvoker pMethod, int pDelay)
        {
            if (_runDelegates == null)
            {
                _runDelegates = new Timer();
                _runDelegates.Tick += RunDelegates;
            }
            else
            {
                _runDelegates.Stop();
            }

            _delayedDelegates.Add(pMethod, DateTime.Now + TimeSpan.FromMilliseconds(pDelay));

            StartTimer();
        }

        private void StartTimer()
        {
            if (_delayedDelegates.Count > 0)
            {
                int delay = FindSoonestDelay();
                if (delay == 0)
                {
                    RunDelegates();
                }
                else
                {
                    _runDelegates.Interval = delay;
                    _runDelegates.Start();
                }
            }
        }

        private int FindSoonestDelay()
        {
            int soonest = int.MaxValue;
            TimeSpan remaining;

            foreach (MethodInvoker invoker in _delayedDelegates.Keys)
            {
                remaining = _delayedDelegates[invoker] - DateTime.Now;
                soonest = Math.Max(0, Math.Min(soonest, (int)remaining.TotalMilliseconds));
            }

            return soonest;
        }

        private void RunDelegates(object pSender = null, EventArgs pE = null)
        {
            try
            {
                _runDelegates.Stop();

                List<MethodInvoker> removeDelegates = new List<MethodInvoker>();

                foreach (MethodInvoker method in _delayedDelegates.Keys)
                {
                    if (DateTime.Now >= _delayedDelegates[method])
                    {
                        method();

                        removeDelegates.Add(method);
                    }
                }

                foreach (MethodInvoker method in removeDelegates)
                {
                    _delayedDelegates.Remove(method);
                }
            }
            catch (Exception ex)
            {
            }
            finally
            {
                StartTimer();
            }
        }
    }
}
使用System.Windows.Forms;
使用System.Collections.Generic;
使用制度;
名称空间MyTool
{
公共类延迟删除
{
静态私有DelayedDelegate_实例=null;
专用计时器_runDelegates=null;
专用词典_delayedDelegates=新词典();
公共延迟删除门()
{
}
静态私有DelayedDelegate实例
{
得到
{
if(_instance==null)
{
_实例=新的DelayedDelegate();
}
返回_实例;
}
}
公共静态void Add(MethodInvoker-pMethod,int-pDelay)
{
Instance.AddNewDelegate(pMethod,pDelay*1000);
}
公共静态void add毫秒(MethodInvoker pMethod,int pDelay)
{
AddNewDelegate(pMethod,pDelay);
}
私有void AddNewDelegate(MethodInvoker-pMethod,int-pDelay)
{
如果(_runDelegates==null)
{
_runDelegates=新计时器();
_runDelegates.Tick+=runDelegates;
}
其他的
{
_runDelegates.Stop();
}
_delayedDelegates.Add(pMethod,DateTime.Now+TimeSpan.frommilluses(pDelay));
StartTimer();
}
私有void StartTimer()
{
如果(_delayedDelegates.Count>0)
{
int delay=FindSoonestDelay();
如果(延迟==0)
{
RunDelegates();
}
其他的
{
_运行代理。间隔=延迟;
_runDelegates.Start();
}
}
}
私有int FindSoonestDelay()
{
int soosest=int.MaxValue;
剩余时间跨度;
foreach(delayedDelegates.Keys中的MethodInvoker调用程序)
{
剩余=_delayedDelegates[invoker]-DateTime.Now;
soonest=Math.Max(0,Math.Min(最快,(int)剩余的.total毫秒));
}
尽快返回;
}
私有void RunDelegates(对象pSender=null,事件args pE=null)
{
尝试
{
_runDelegates.Stop();
List removeDelegates=新列表();
foreach(delayedDelegates.Keys中的MethodInvoker方法)
{
如果(DateTime.Now>=\u delayedDelegates[方法])
{
方法();
移除闸门。添加(方法);
}
}
foreach(RemoveDeleteGates中的MethodInvoker方法)
{
_延迟删除门。删除(方法);
}
}
捕获(例外情况除外)
{
}
最后
public static class DelayedDelegate
{

    static Timer runDelegates;
    static Dictionary<MethodInvoker, DateTime> delayedDelegates = new Dictionary<MethodInvoker, DateTime>();

    static DelayedDelegate()
    {

        runDelegates = new Timer();
        runDelegates.Interval = 250;
        runDelegates.Tick += RunDelegates;
        runDelegates.Enabled = true;

    }

    public static void Add(MethodInvoker method, int delay)
    {

        delayedDelegates.Add(method, DateTime.Now + TimeSpan.FromSeconds(delay));

    }

    static void RunDelegates(object sender, EventArgs e)
    {

        List<MethodInvoker> removeDelegates = new List<MethodInvoker>();

        foreach (MethodInvoker method in delayedDelegates.Keys)
        {

            if (DateTime.Now >= delayedDelegates[method])
            {
                method();
                removeDelegates.Add(method);
            }

        }

        foreach (MethodInvoker method in removeDelegates)
        {

            delayedDelegates.Remove(method);

        }


    }

}
DelayedDelegate.Add(MyMethod,5);

void MyMethod()
{
     MessageBox.Show("5 Seconds Later!");
}
using System.Windows.Forms;
using System.Collections.Generic;
using System;

namespace MyTool
{
    public class DelayedDelegate
    {
       static private DelayedDelegate _instance = null;

        private Timer _runDelegates = null;

        private Dictionary<MethodInvoker, DateTime> _delayedDelegates = new Dictionary<MethodInvoker, DateTime>();

        public DelayedDelegate()
        {
        }

        static private DelayedDelegate Instance
        {
            get
            {
                if (_instance == null)
                {
                    _instance = new DelayedDelegate();
                }

                return _instance;
            }
        }

        public static void Add(MethodInvoker pMethod, int pDelay)
        {
            Instance.AddNewDelegate(pMethod, pDelay * 1000);
        }

        public static void AddMilliseconds(MethodInvoker pMethod, int pDelay)
        {
            Instance.AddNewDelegate(pMethod, pDelay);
        }

        private void AddNewDelegate(MethodInvoker pMethod, int pDelay)
        {
            if (_runDelegates == null)
            {
                _runDelegates = new Timer();
                _runDelegates.Tick += RunDelegates;
            }
            else
            {
                _runDelegates.Stop();
            }

            _delayedDelegates.Add(pMethod, DateTime.Now + TimeSpan.FromMilliseconds(pDelay));

            StartTimer();
        }

        private void StartTimer()
        {
            if (_delayedDelegates.Count > 0)
            {
                int delay = FindSoonestDelay();
                if (delay == 0)
                {
                    RunDelegates();
                }
                else
                {
                    _runDelegates.Interval = delay;
                    _runDelegates.Start();
                }
            }
        }

        private int FindSoonestDelay()
        {
            int soonest = int.MaxValue;
            TimeSpan remaining;

            foreach (MethodInvoker invoker in _delayedDelegates.Keys)
            {
                remaining = _delayedDelegates[invoker] - DateTime.Now;
                soonest = Math.Max(0, Math.Min(soonest, (int)remaining.TotalMilliseconds));
            }

            return soonest;
        }

        private void RunDelegates(object pSender = null, EventArgs pE = null)
        {
            try
            {
                _runDelegates.Stop();

                List<MethodInvoker> removeDelegates = new List<MethodInvoker>();

                foreach (MethodInvoker method in _delayedDelegates.Keys)
                {
                    if (DateTime.Now >= _delayedDelegates[method])
                    {
                        method();

                        removeDelegates.Add(method);
                    }
                }

                foreach (MethodInvoker method in removeDelegates)
                {
                    _delayedDelegates.Remove(method);
                }
            }
            catch (Exception ex)
            {
            }
            finally
            {
                StartTimer();
            }
        }
    }
}
private static volatile List<System.Threading.Timer> _timers = new List<System.Threading.Timer>();
        private static object lockobj = new object();
        public static void SetTimeout(Action action, int delayInMilliseconds)
        {
            System.Threading.Timer timer = null;
            var cb = new System.Threading.TimerCallback((state) =>
            {
                lock (lockobj)
                    _timers.Remove(timer);
                timer.Dispose();
                action()
            });
            lock (lockobj)
                _timers.Add(timer = new System.Threading.Timer(cb, null, delayInMilliseconds, System.Threading.Timeout.Infinite));
}
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 ();
    }
}
public void Execute(object parameter)
{
    if (!IsDebouncing) {
        IsDebouncing = true;
        AsyncUtils.DelayCall (DebouncePeriodMsec, () => {
            IsDebouncing = false;
        });

        _execute ();
    }
}
public void foo()
{
    Task.Delay(1000).ContinueWith(t=> bar());
}

public void bar()
{
    // do stuff
}
class CancelableDelay
    {
        Thread delayTh;
        Action action;
        int ms;

        public static CancelableDelay StartAfter(int milliseconds, Action action)
        {
            CancelableDelay result = new CancelableDelay() { ms = milliseconds };
            result.action = action;
            result.delayTh = new Thread(result.Delay);
            result.delayTh.Start();
            return result;
        }

        private CancelableDelay() { }

        void Delay()
        {
            try
            {
                Thread.Sleep(ms);
                action.Invoke();
            }
            catch (ThreadAbortException)
            { }
        }

        public void Cancel() => delayTh.Abort();

    }
var job = CancelableDelay.StartAfter(1000, () => { WorkAfter1sec(); });  
job.Cancel(); //to cancel the delayed job