2

タスクを作成する次のコードがあります。

 Task.Factory.StartNew(() =>
                        {
                            ExtractStuff(fileName);
                        });

時々、中で数秒間一時停止する必要がありますExtractStuff

レギュラーを使っても大丈夫Thread.Sleep(1000)ですか?または、実行中のタスクを一時停止する別の方法はありますか?

4

4 に答える 4

3

Thread.Sleepは、タスクを実行しているスレッドをブロックします(これは理想的ではありません)が、多数のタスクを並行して実行していない限り、許容できる妥協案(リスクが低く、パフォーマンスに大きな問題はない)になる可能性があります。 。.NET 4.5には、「async / await」とTask.Delayでいくつかの改善があり、タイマーに基づいて継続を暗黙的に設定します(実行中のスレッドをブロックする必要はありません)が、4.0では直接利用できません。

次のような方法で同じことを自分で行うことができます(あまりテストされていないため、注意して使用してください)。

class Program
{
    static void Main(string[] args)
    {
        var fullAction = RunActionsWithDelay(DoSomething, 2000, DoSomethingElse);
        fullAction.Wait();
        Console.WriteLine("Done");
        Console.ReadLine();
    }

    static Task RunActionsWithDelay(Action first, int delay, Action second)
    {
        var delayedCompletion = new TaskCompletionSource<object>();
        var task = Task.Factory.StartNew(DoSomething);
        task.ContinueWith(t =>
        {
            if (t.IsFaulted)
            {
                delayedCompletion.SetException(t.Exception);
            }
            else
            {
                Timer timer = null;
                timer = new Timer(s =>
                {
                    try
                    {
                        DoSomethingElse();
                        delayedCompletion.SetResult(null);
                    }
                    catch (Exception ex)
                    {
                        delayedCompletion.SetException(ex);
                    }
                    finally
                    {
                        timer.Dispose();
                    }
                }, null, delay, Timeout.Infinite);                    
            }

        });
        return delayedCompletion.Task;
    }

    static void DoSomething()
    {
        Console.WriteLine("Something");
    }

    static void DoSomethingElse()
    {
        Console.WriteLine("Something Else");
    }
}

これはかなり醜いですが、上記よりも少しうまくカプセル化できます。「ハングする」スレッドは排除されますが、継続の設定に関連する追加のパフォーマンスオーバーヘッドがあります。多数の並列タスクを実行していて、それらすべてに遅延を導入する必要がある場合にのみ、これを実行することをお勧めします。

于 2012-08-22T21:52:57.563 に答える
2

これを行っても問題ないと思いますが、 TaskCreationOptions.LongRunningを使用することをお勧めします。

Task.Factory.StartNew(() =>
                    {
                        ExtractStuff(fileName);
                    },TaskCreationOptions.LongRunning);
于 2012-08-22T20:58:54.303 に答える
1

ExtractStuff の実行を遅らせる必要がある場合は、ThreadPool.RegisterWaitForSingleObject を見て、設定されていない WaitHandle と組み合わせることができます。

private static WaitHandle NeverSet = new WaitHandle();
private void ExtractStuff(object state)
{
    string filename = state as string;
    ....
}

private void StartExtract(string filename);
{
    ThreadPool.RegisterWaitForSingleObject(NeverSet, ExtractStuff, fileName, seconds * 1000, true);
}

これがあなたの探求に役立つことを願っています。

于 2012-08-22T21:05:27.987 に答える
0

Task.Delay(timeout) を使用して、 ExtractStuff メソッド内でそれを待つことができます。

private async string ExtractStuff(fileName)
{
   // Your Code
   await Task.Delay(timeout);
}
于 2016-11-29T15:16:31.733 に答える