2017-02-23 36 views
2

我有一種情況,當用戶點擊一個tabitem時,用戶創建一個類的實例。這個類包含一個繪製圖形的函數,它非常耗時,因此它被寫入異步。如何等待第一個代碼正在執行?

現在問題是讓用戶第一次點擊選項卡並且類實例化,並且長時間處理工作很長時間,同時前一個異步任務沒有被縮短並且用戶再次點擊同一個tabitem。

在這種情況下,我必須等到上一個異步任務沒有完成,然後第二次點擊到tabitem之後,必須先創建實例後才能完成異步任務(應該等到第一個異步進程沒有被縮短)。

的代碼是在這裏:

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類的構造函數我這樣做:

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

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

什麼,我想,當用戶點擊第二次此選項卡項目數= 2那麼必須等到先前的異步任務爲finsh,然後它必須再次實例化DrawGraph類到 再次重新啓動異步。

如何實現它?

+1

爲什麼不禁用該選項卡? –

+1

@HristoYankov是的,我有這個想法,但沒有被我的大四接受。 –

回答

3

在這種情況下,我必須等到前面的異步任務格蘭拳頭異步任務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(); 
} 

注意,這需要你使用async Task代替async void,這是很好的,因爲無論如何,你應該avoid async void

-1

一個簡單的變化將實現這一

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

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

我做了DrawGraph()回報Task以及萬一你需要等待它。

+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; 
     ... 
    }); 
} 

更新下

如這裏看到的,你可以調用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任務正在處理時等待if(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

條件drawGraphTask == null甚至會執行第二次點擊,因爲第二次點擊後調試的參數是這些「Id = 744,Status = RanToCompletion,Method =」{null}「」但它仍然執行這個條件 –

+0

不,該條件檢查Task是否爲null,這與任務的Method屬性具有的值無關。 – NineBerry

相關問題