2017-08-07 56 views
1

我在C#中創建一個代碼,其中我從Access數據庫中提取一些記錄,但我需要一段時間去下一個迭代以取決於點擊一個按鈕。我嘗試了一些線程或任務,但它沒有工作,因爲它阻止了我需要它看到和點擊的UI。C# - 使用UI功能,像一個無限循環,直到按下按鈕

下面的代碼:

bool nextClick = false ; 

       while (readerSelect.Read()) 
       { 

        // show the correct panel 
        if (string.Compare(readerSelect[2].ToString(), "P1") == 0) 
        { 
         // panel with type 1 
         textBoxP1Text1.Text = readerSelect[3].ToString(); 
         textBoxP1Text2.Text = readerSelect[4].ToString(); 
         pictureBoxP1Image.ImageLocation = readerSelect[6].ToString(); 

        } 
        else 
        { 
         // panel with type 2 
         textBoxP1Text2.Text = readerSelect[5].ToString(); 
        } 

    //this while need to be kind of infinite so the interation can't be processed and 
    //so when i need to change iteration i click the buttonNext 
        while (!nextClick) { 
        startWhile:; 
         MethodInvoker mi = delegate() { 
          if (nextClick) 
          { 
           Application.DoEvents(); 
           // System.Windows.Forms.Application.Run(); 
          } 

         }; 
         this.Invoke(mi); 
         //break; 
         goto startWhile; 
        } 

private void buttonNext_Click(object sender, EventArgs e) 
    { 
     // click on the next button 
     nextClick = true; 
    } 
+1

如果您只需點擊一下即可轉到下一個項目,請不要使用while循環...只需在每次點擊時執行一次... – Milney

+0

這將對我們的連接產生重大影響,差,但謝謝你回答 –

+0

你是什麼意思'對你的連接有重大影響'?這只是不正確的。你現在和現在這樣做的方式只會讀取有多少記錄。你誤會了。我建議閱讀DataReader文檔,直到你更好地理解它作爲第一點 – Milney

回答

2

雖然達克斯Fohl的答案的作品,好像你已經得到了你的設計有問題。我認爲你在Form課上有太多的商業邏輯正在違反Single Responsibility Principle

我建議將業務邏輯分解爲它自己的類。然後,而不是遍歷循環中的所有內容,只需按下按鈕單擊事件即可處理下一條記錄並顯示結果。這裏是我的意思的一個例子:

public partial class Form1 : Form 
{ 
    private readonly DataProcessor dataProcessor = new DataProcessor(); 

    public Form1() 
    { 
     this.InitializeComponent(); 
    } 

    private void button1Next_Click(object sender, EventArgs e) 
    { 
     this.buttonNext.Enabled = false; 
     this.ProcessNext(); 
    } 

    private async void ProcessNext() 
    { 
     string s = await this.dataProcessor.ProcessNext(); 
     this.textBoxP1Text1.Text = s; 
     this.buttonNext.Enabled = true; 
    } 
} 

public class DataProcessor 
{ 
    private readonly Random r = new Random(); // Or reader or whatever. 

    public async Task<string> ProcessNext() // Just using `string` as an example. 
    { 
     await Task.Delay(1000); 
     return this.r.Next().ToString(); 
    } 
} 

我認爲這將會更容易理解,並在將來更易於維護。當一個新的團隊成員查看信號量(或未來的自我)時,很難理解/記住所有這一切的重點。在這裏,你只需要一個本地功能來完成一件事,而且很容易就能完成。

3

您可以使用異步任務內的信號,有按鈕Release它每一次點擊中,並有while循環通過每一次等待着它。這裏有一個簡單的例子,使用具有button1形式和label1添加到它:

public partial class Form1 : Form 
{ 
    private readonly SemaphoreSlim signal = new SemaphoreSlim(0, int.MaxValue); 

    public Form1() 
    { 
     this.InitializeComponent(); 
     this.RunLoop(); 
    } 

    private async void RunLoop() 
    { 
     var i = 0; 
     while (true) 
     { 
      this.label2.Text = $"Enqueued: {this.signal.CurrentCount}"; 
      await this.signal.WaitAsync(); // Wait button click async 
      await Task.Delay(1000); // Simulate work 
      this.label1.Text = $"Completed: {++i}"; 
     } 
    } 

    private void button1_Click(object sender, EventArgs e) 
    { 
     this.signal.Release(); 
     this.label2.Text = $"Enqueued: {this.signal.CurrentCount + 1}"; 
     // Or if you want to limit the # people can queue up, then put this whole 
     // thing in an `if (signal.CurrentCount < myLimit)` block, and optionally 
     // disable the button once limit has been reached, and re-enable it right 
     // before the `WaitAsync` call above. 
    } 
} 
+0

如果用戶在運行循環完成時單擊多次,是否可能導致SemaphoreFullException?我曾想過其中一個EventWaitHandle類會更合適。 –

+0

@MartinBrown是的,剛剛更新的答案說明了這一點。 –

+0

非常感謝,這對我來說很有效:) –

相關問題