この回答は、@svick のコメントに基づいています。
メソッドのすべての「作業」を呼び出し元と同じスレッドで実行したいが、キャンセルの目的でスレッド プール スレッドが使用されても構わないと仮定します (I' mは、タイマーが起動したときにスレッド プール スレッドを使用しますTask.Delay。Timer
Taskとはいえ、メソッドが返されたときに Task が完了したことが確実にわかるため、 は必要ありません。タイムアウトのある通常の方法だけで十分です。
static void DoSomethingOrThrowAfterTimeout(int millisecondsTimeout)
{
    CancellationTokenSource cts = new CancellationTokenSource(millisecondsTimeout);
    CancellationToken ct = cts.Token;
    // do some work
    ct.ThrowIfCancellationRequested();
    // do more work
    ct.ThrowIfCancellationRequested();
    // repeat until done.
}
明らかに、協調的なキャンセルを使用するこのアプローチでは、メソッド内の作業をどれだけ小さく分割できるかに依存するため、メソッドはタイムアウトで正確にタイムアウトしません。
別のスレッドの使用を回避したい場合 ( のためにCancellationTokenSource)、開始時間を追跡し、メソッドのさまざまなポイントで (タイムアウトを超えたかどうかを確認するために) 経過時間を確認できます (どのようにct.ThrowIfCancellationRequested()上で使用されます。