2017-07-27 3 views
1

こんにちは、テキストが変更されたテキストボックスを持っています。文字がテキストボックスに挿入されるたびに、テキスト変更イベントが発生します。 Text changedイベントは非同期タスクメソッドを呼び出します。以下は、私のイベントと非同期タスクメソッドです。非同期タスクメソッド呼び出しが同期的に実行されるようにする方法

public Textbox_TextChangedEvent() 
    { 
     GetStocks(texboxText); 
    } 

public async Task GetStocks(string texboxText) 
    { 
     IsBusy = true; 
     await Task.Run(() => { CreateCollection(texboxText); }); 
     IsBusy = false; 
    } 

質問 は、どのように私は確信してGetStocksメソッドが同期次々と呼ばれていることができます。

ユーザが入力テキストとしてTedを入力したとします。それから私は、非同期呼び出しが次々と完了するのを望みます。 、つまり、GetStocksを次の順序で呼び出し、次の順序でタスクを完了する必要があります。

  1. GetStocks(T)
  2. GetStocks(TE)
  3. GetStocks(テッド)
+0

どのように希望する動作は、現在の動作よりも違うのですか? –

+0

あなたはどのフレームワークを使用していますか?これはデスクトップアプリですか、ウェブアプリですか? – Michael

+0

aaah作業をキューに入れたい場合は、キューを使用して作業を保存してから、順番に処理してください。 – user230910

答えて

-1

簡単オプション、状況によっては次のようになります。

public async Task GetStocks(string texboxText) 
{ 
    Task.Run(() => { 
     IsBusy = true; 
     CreateCollection(texboxText); 
     IsBusy = false; 

    }); 
} 
+0

申し訳ありませんが、上記のコードは私のためには機能しませんでした。実際に私がここで直面している問題は、私の質問に記載された順序で、3つの非同期呼び出しが行われます。1.GetStocks(T) 2.GetStocks(Te) 3.GetStocks(Ted)。しかし、私が結果を返す順序は3,2,1です。しかし、結果は1,2,3 – Vinay

0

解決するためにこのような問題は、以前のプロジェクトAsyncLockを使用しました。 AsyncLockは、前回のロックが解除されるまで待機します。

AsyncLockは少し複雑に見えるかもしれませんが、提供された使用例がその動作を説明することを願っています。

public class AsyncLock 
{ 
    private TaskCompletionSource<object> _lastSection; 

    public AsyncLock() 
    { 
     _lastSection = new TaskCompletionSource<object>(); 
     _lastSection.SetResult(null); 
    } 

    public class ReleaseLock : IDisposable 
    { 
     private readonly TaskCompletionSource<object> _tcs; 

     public ReleaseLock(TaskCompletionSource<object> tcs) 
     { 
     _tcs = tcs; 
     } 

     public void Dispose() 
     { 
     _tcs.SetResult(null); 
     } 
    } 

    /// <summary> 
    /// Enters and locks a critical section as soon as the currently executing task has left the section. 
    /// The critical section is locked until the returned <see cref="IDisposable"/> gets disposed. 
    /// </summary> 
    public Task<ReleaseLock> EnterAsync() 
    { 
     var newTcs = new TaskCompletionSource<object>(); 
     var toAwait = Interlocked.Exchange(ref _lastSection, newTcs); 
     return toAwait.Task.ContinueWith((_) => new ReleaseLock(newTcs), TaskContinuationOptions.ExecuteSynchronously); 
    } 
} 

await AsyncLock.EnterAsync()を使用すると、前回のロックが解除されるまで待つことができます。 EnterAsyncでは、Taskの後に次のTaskの後にContinueWithを使用してキューします。つまり、await AsyncLock.EnterAsync()は前回の処理が完了した後に実行されます。ここ

using (await _lock.EnterAsync()) 
{ 
    // ... 
} 

は使用例である:

class Program 
{ 
    private static readonly AsyncLock _lock = new AsyncLock(); 

    private static async Task Test(int i, Task toComplete) 
    { 
     using (await _lock.EnterAsync()) 
     { 
     await toComplete; 
     Console.WriteLine(i); 
     } 
    } 

    public static void Main(string[] args) 
    { 
     var tcs1 = new TaskCompletionSource<object>(); 
     var tcs2 = new TaskCompletionSource<object>(); 

     Task.Run(async() => 
     { 
     var t1 = Test(1, tcs1.Task); // start first task 
     var t2 = Test(2, tcs2.Task); // start second task 

     tcs2.SetResult(null); // finish second first 
     tcs1.SetResult(null); // fiish last task 

     await Task.WhenAll(t1, t2); // will print: 1 and then 2 
     }).Wait(); 
    } 
} 

Test方法は、最初Asyncロックに入るかかり、タスクtoCompleteを待って、その後コンソールに書き込みます。

我々は2つのTestタスク("1"、および"2")を開始し、第一、第二toCompleteを完了します。 AsyncLockがなければ、前の例では"2","1"が表示されます。 AsyncLockでは、タスクは開始された順序で処理されます。

備考: 1つの最後の発言。これにより処理オーダーが達成されますが、時には面倒なこともあります。このようなロックを使用すると、デッドロックが発生しやすくなります。デッドロックは、解決しにくく、最初に見つけにくいものです。 ロックをよくご使用ください

編集:ここでは使用例あなたの問題:

private readonly AsyncLock _lock = new AsyncLock(); 

public Textbox_TextChangedEvent() 
{ 
    GetStocks(texboxText); // every call is now "queued" after the previous one 
} 

public async Task GetStocks(string texboxText) 
{ 
    using(await _lock.EnterAsync()) 
    { 
     IsBusy = true; 
     await Task.Run(() => { CreateCollection(texboxText); }); 
     IsBusy = false; 
    } 
} 
+0

の順番で戻って欲しいです。 'EnterAsync'の中の' ContinueWith'が異常です。状態として 'newTcs'を渡すだけで、それはデリゲートによって無視されますか?途中で放棄されたローカル変数のクローズを回避しようとする試みのように感じます。この 'AsyncLock'バージョンを思い出させます(これは実際に状態を使用します):https://blogs.msdn.microsoft.com/pfxteam/2012/02/12/building-async-coordination-primitives-part-6- asynclock /) –

+0

@KirillShlenskiyあなたは正しいです。このパラメータはオプションではない古いSilverlightプロジェクトのコードを入手しました。答えを更新します。 – Iqon

関連する問題