2017-02-23 4 views
2

私は、ユーザーがタブアイテムをクリックしたときにクラスのインスタンスを作成する状況があります。このクラスにはグラフをプロットする関数が含まれており、非常に時間がかかり、非同期で書かれています。最初のコードが実行されているのを待つ方法は?

問題はユーザーが最初にタブをクリックしてクラスがインスタンス化され、長いプロセスが長い時間働く一方で、以前の非同期タスクが壊れておらず、同じタブアイテムで再度クリックされたということです。

この状況では、前回の非同期タスクが終了してから次のタップすると、最初の非同期処理が終了した後にインスタンスを作成する必要があります。

コードはここにある:

if (selectedTabIndex == 2) //What is the user selected second time whil the previous task is still not finshed ? 
{   
    DrawGraph obj= new DrawGraph(selectedItem.Name); 
} 
どこかDrawGraphクラスのコンストラクタで

私が行っている:ユーザーはこのタブ項目数= 2、それを二回クリックしたときに

public DrawGraph(string Name) 
{ 
    timeConsumingProcess(Name); 
} 

public async void timeConsumingProcess(string Name) 
{  
    await startTaimeConsumingProcess(); 
} 

は何私が欲しいのです以前の非同期タスクがfinshになるまで待たなければならず、次に再びDrawGraphクラスをインスタンス化する必要があります。 asyncを再起動してください。

どのように達成するには?

+1

なぜタブを無効にしないのですか? –

+1

@HristoYankovええ、私はその考えを持っていたが、それは私の上級生に受け入れられなかった。 –

答えて

3

私は、あなたのコード(A)が、以前の非同期タスクが完了していないまで待たなければならないとtehの拳非同期タスクが

をfinshedされた後、その後のTabItemへの第二のクリックでインスタンスを作成する必要があります。

private Task drawGraph = null; 
... 
if (selectedTabIndex == 2) 
{ 
    if (drawGraph != null) 
    await drawGraph; 
    DrawGraph obj = new DrawGraph(selectedItem.Name); 
    drawGraph = obj.timeConsumingProcess(); 
} 

... 

private readonly string name; 
public DrawGraph(string Name) 
{ 
    name = Name; 
} 

public async Task timeConsumingProcess() 
{ 
    await startTaimeConsumingProcess(); 
} 

注これはあなたがavoid async voidなければならないので、とにかく良いである、async Task代わりのasync voidを使用する必要があること:最後のタスクを待ちます。

-1

単純な変更は、私はあなたがそれを待つ必要がある場合にもDrawGraph()リターンTaskを作っこの

public async Task DrawGraph(string Name) 
{ 
    await timeConsumingProcess(Name); 
} 

public async Task timeConsumingProcess(string Name) 
{  
    await startTaimeConsumingProcess(); 
} 

を実現します。

+0

awaitを使用してもユーザー操作の処理が妨げられることはないため、問題は残ります。 – NineBerry

+0

@NineBerryあなたは正しいです。しかし、それはユーザーが尋ねたものではありません。ユーザは、ボタンが押されていても待つべきタスクを尋ねました。したがって、 'DrawGraph()'への次の呼び出しは前のものを完了するのを待ちます。 –

1

、それは非常に時間のかかるプロセスである場合は、あなたが別のスレッド

public DrawGraph(string Name) 
{ 
    var task = new Task(() => timeConsumingProcess(Name)); 
    task.Start(); 
} 

あなたのメインスレッドがブロックされることはありません。この方法でそれを行うことを選択することができます。この長期実行タスクが終了した後でコードを実行する場合は、ContinueWithメソッドを使用します。

public DrawGraph(string Name) 
{ 
    _canPressTab = false; 
    var task = new Task(() => timeConsumingProcess(Name)); 
    task.Start(); 
    task.ContinueWith(t => { 
     _canPressTab = true; 
     ... 
    }); 
} 

BELOW UPDATEここに見られるように、あなたがタブをクリックすると、あなたはDrawメソッドを呼び出すことができます。これは、タスクがすでに実行中であるかどうかをチェックします。そうでない場合は、タスクを開始します。タスクが実行されている場合は、タスクが完了するまで待ってから新しいタスクを開始します。

public Task task = new Task(DoSomething); 
    private static void DoSomething() 
    { 
     Thread.Sleep(10000); 
    } 


    private void Draw() 
    { 
     //if tab is clicked run the Draw method 
     if (task.Status.Equals(TaskStatus.Running)) 
     { 
      task.Wait(); 
      task = new Task(DoSomething); 
      task.Start(); 
     } 
     else if (task.Status.Equals(TaskStatus.RanToCompletion)) 
     { 
      task = new Task(DoSomething); 
      task.Start(); 
     } 
     else 
     { 
      task.Start(); 
     } 
    } 
+0

私がしなければならないのは、previosuタスクがproocessingしている間に(selectedTabIndex == 2)の条件を待つことです。処理している場合は、それをフィンイングさせ、次のインスタンスを処理します。どうやってするの ? –

+0

私の例を更新しました。これは、あなたの望むことですか? – user2657943

1

長期実行アクションを表すタスクをフォームのインスタンス変数に格納し、これを使用してタスクがまだ実行中かどうかを確認できます。

private Task drawGraphTask = null; 

private void button1_Click(object sender, EventArgs e) 
{ 
    DrawGraph(); 
} 

private async void DrawGraph() 
{ 
    // Only perform task when this is the first time 
    // or the previous task is already completed 
    if (drawGraphTask == null || drawGraphTask.IsCompleted) 
    { 
     drawGraphTask = startTimeConsumingProcess(); 
     await drawGraphTask; 
    } 
    else 
    { 
     MessageBox.Show("Task already active"); 
    } 
} 

private Task startTimeConsumingProcess() 
{ 
    // Your Code here 
    return Task.Delay(5000); 
} 

コンストラクタ内から非同期アクティビティを開始するのは良いことではありません。非同期ロジックをDrawGraphクラスの外に移動し、フォームのレベルでクラスを非同期にインスタンス化します。この状況で

+0

2番目のクリック後のデバッグ時のパラメータがこれらの "Id = 744、Status = RanToCompletion、Method =" {null} ""であるにもかかわらず、thsi条件を実行しているので、drawGraphTask == nullの条件が実行されます。 –

+0

いいえ、タスクは、タスク全体がnullであるかどうかをチェックします。タスクのMethodプロパティには、どの値の値でもかまいません。 – NineBerry

関連する問題