如何在 C# 中编写 Timeoutable 方法

发布于 2024-10-16 20:38:09 字数 192 浏览 1 评论 0原文

我的方法需要更长的时间来执行并且涉及大量的数据库操作。我想将这些方法包装在可超时方法中,这样如果它没有在恒定时间内回调,我就会回滚。

有什么办法可以做到这一点,我也必须在主线程中运行该方法,因为我使用的第 3 方 com 对象无法在后台线程中执行。

任何形式的建议都将受到高度赞赏。

问候,

比贝克·达瓦迪

I have methods which take longer time to execute and involve lots of database operations. I want to wrap these methods within timeoutable method so that if it didn't callback within constant time, I will rollback.

Is there any way to do this, also I have to run the method in the main thread only becuase the 3rd party com objects I am using cannot be executed in background thread.

Any kind of suggestion will be highly appreciated.

regards,

Bibek Dawadi

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

绮烟 2024-10-23 20:38:09

我拼凑了一个与链接的解决方案类似的解决方案,只是我使用 Thread.Interrupt() 而不是 Thread.Abort(),认为这对主线程会更友好一些。问题是 Thread.Interrupt() 不会中断被阻塞的调用,因此在很多情况下都不能令人满意。 Thread.Abort() 是一个危险的调用,应尽可能避免。选择你的毒药。

对于它的价值,这是我的实现:

public static class AbortableProc
{

    public static void Execute(Action action, Action timeoutAction, int milli)
    {
        Thread currThread = Thread.CurrentThread;
        object stoppedLock = new object();
        bool stopped = false;
        bool interrupted = false;

        Thread timer = new Thread(() =>
        {
            Thread.Sleep(milli);
            lock (stoppedLock)
            {
                if (!stopped)
                {
                    currThread.Interrupt();
                    stopped = true;
                    interrupted = true;
                }
            }
        });
        timer.Start();

        try
        {
            action();
            lock (stoppedLock)
            {
                stopped = true;
            }
        }
        catch (ThreadInterruptedException)
        {
        }
        if (interrupted)
        {
            timeoutAction();
        }
    }
}

为了笑,我放入了一个 timeoutAction ,以便您可以在这种模式下使用它:

AbortableProc.Execute(
    () => { Process(kStarting); Process(kWorking); Process(kCleaningUp); },
    () => { if (IsWorking()) CleanUp(); }
};

I knocked together a solution similar to the one linked to, except that I used Thread.Interrupt() instead of Thread.Abort(), thinking that would be a little kinder to the main thread. The problem is that Thread.Interrupt() won't interrupt a call that is blocked, so it is unsatisfactory under many cases. Thread.Abort() is a dangerous call and should be avoided where possible. Pick your poison.

For what it's worth, this is my implementation:

public static class AbortableProc
{

    public static void Execute(Action action, Action timeoutAction, int milli)
    {
        Thread currThread = Thread.CurrentThread;
        object stoppedLock = new object();
        bool stopped = false;
        bool interrupted = false;

        Thread timer = new Thread(() =>
        {
            Thread.Sleep(milli);
            lock (stoppedLock)
            {
                if (!stopped)
                {
                    currThread.Interrupt();
                    stopped = true;
                    interrupted = true;
                }
            }
        });
        timer.Start();

        try
        {
            action();
            lock (stoppedLock)
            {
                stopped = true;
            }
        }
        catch (ThreadInterruptedException)
        {
        }
        if (interrupted)
        {
            timeoutAction();
        }
    }
}

For grins, I put in a timeoutAction so that you could use it in this mode:

AbortableProc.Execute(
    () => { Process(kStarting); Process(kWorking); Process(kCleaningUp); },
    () => { if (IsWorking()) CleanUp(); }
};
玩心态 2024-10-23 20:38:09

我一直在你身边,直到你说你需要它在主线程中运行。我认为按照你描述的方式是不可能的。

问题是您将需要至少两个线程来执行计时和实际工作,并且这两个线程都不能成为主线程,因为计时器不会使用主线程,并且因为您需要终止操作,如果它是主线程,则会关闭整个应用程序。通常执行此操作的方法是设置一个从主线程运行的包装类,并设置操作的后台线程以及计时器。

究竟为什么必须从主线程调用第 3 方库?

I was with you till you said you needed it to run in the main thread. I don't think it's possible the way you describe.

The problem is that you're going to need at least two threads to perform the timing and the actual work, and neither of those can be the main thread because a timer won't use the main thread, and because you'll want the operation to terminate, which if it were the main thread would shut down the whole app. The way you would do this normally is to set up a wrapper class that is run from the main thread and sets up the background thread for the operation as well as the timer.

Why, exactly, does the 3rd party library have to be invoked from the main thread?

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文