0

トランザクションのように動作する長時間実行されるタスクがあります。これには、1 つの成功が別の成功に依存する多くの操作が含まれます。

class MyTransaction
{
    public void Execute()
    {
        StopServices();
        BackupFiles();
        OverwriteFiles();
        BackupDatabases();
        RunChangeScripts();
        ... and few others        
    }

    public void RollBack() { }
}

class MyTransactionManager
{
    public RunTransactions()
    {
        Task.Factory.StartNew(() => {
            new MyTransaction().Execute();
        });
    }
}

これは、システムのさまざまなコンポーネントによってさまざまな操作が提供される実際のアプリケーションの単なる擬似コードです。進行状況バーを使用して進行状況を表示する基礎となる GUI (WinForms) と、何が起こっても応答性を維持する必要がある他のいくつかのものがあります。トランザクションはすべて非常に長時間実行されるため、( を使用して) タスクを開始するときに指定する必要はありませんTaskCreationOptions。常に新しいスレッドで実行されます。トランザクションの進行状況は、イベントを使用して GUI に報告されます。

現在、トランザクションの実行中に何かが失敗した場合、現在のようにすぐにロールバックしないという要求があります。彼らは、ロールバックするか、エラーを修正して、最後に成功したポイントから続行するかを決定するオプションをユーザーに提供するメッセージ ボックスを GUI にポップアップ表示したいと考えています。

したがって、何らかの方法でブロッキングを実装する必要があります。私は、別のイベントを発生させ、メッセージ ボックスをポップアップして、「ねえ、修正してから [OK] を押してください」と言うことができると考えました。そして、その OK クリック イベントを外部マネージャー (パブリック API) にバインドし、リクエストをトランザクションに直接委任できます。また、ブロッキングは、ブール値のプロパティをチェックする while ループをアクティブに実行するだけです。

今はパッシブブロッキングの方がいいと思っていますが、どうすればいいのかわかりません。教えていただけますか?

Thread.Sleep編集:これらのエラーは修正にさまざまな時間がかかる可能性があるため、実際には使用したくありません。エラーとそれを修正している人に依存します。

4

3 に答える 3

1

このようなことを試すことができるかもしれません

private static Task<bool> WaitTillUserInput()
{
    TaskCompletionSource<bool> tcs = new TaskCompletionSource<bool>();
    uiSynchronizationContext.Post(x =>
    {
        if (MessageBox.Show("Do you want to rollback...?", "Please confirm", MessageBoxButtons.YesNo) == DialogResult.Yes)
        {
            tcs.SetResult(true);
        }
        else
        {
            tcs.SetResult(false);
        }
    }, null);
    return tcs.Task;
}

C#5.0

public async void Execute()
{
    ...Do something
    //Encountered an error
    var doRollBack = await WaitTillUserInput();
    if(doRollBack)
    {
      //rollback here
    }
}

C#4.0

public void Execute()
{
    ...Do something
    //Encountered an error
    var doRollBackTask = WaitTillUserInput();
    doRollBackTask.ContinueWith(antecedent =>
    {
        if (antecedent.Result)
        { 
            //rollback here
        }
    });
}
于 2013-10-09T14:15:55.763 に答える
0
    EventWaitHandle _wait;

    private async void buttonStart_Click(object sender, EventArgs e) {
        _wait = new EventWaitHandle(true, EventResetMode.ManualReset);
        await Task.Run(() => GoInc());
    }

    private void buttonPause_Click(object sender, EventArgs e) {
        _wait.Reset();
    }

    private void buttonResume_Click(object sender, EventArgs e) {
        _wait.Set();
    }

    EventWaitHandle _wait;

    private void GoInc() {
        for (int i = 0; i < 10000; i++) {
            _wait.WaitOne();
            Thread.Sleep(100);
        }
    }
于 2016-02-16T22:38:55.343 に答える