簡體   English   中英

C#-使UI功能像無限循環一樣直到按下按鈕

[英]C# - Make UI function during like a infinite loop until button pressed

我用C#編寫了代碼,在其中我從Access數據庫中提取了一些記錄,但是我需要花一點時間進行下一次迭代,這取決於單擊按鈕的情況。 我嘗試了一些“線程”或“任務”,但沒有成功,因為它阻止了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; 
    }

您可以在異步任務中使用信號量,讓按鈕在每次單擊時Release它,並讓while循環每次都等待它。 這是一個簡單的示例,使用添加了button1label1的表單:

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.
    }
}

盡管達克斯·弗爾(Dax Fohl)的答案有效,但似乎您的設計中存在問題。 我認為您通過在Form類中進行過多的業務邏輯違反了“ 單一責任原則”

我建議將業務邏輯分解為自己的類。 然后,您無需讓整個過程循環運行,而只需讓按鈕click事件處理下一條記錄並顯示結果即可。 這是我的意思的示例:

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();
    }
}

我認為這在將來會更容易理解和維護。 當新的團隊成員查看信號量的東西(或您未來的自我)時,將很難理解/記住所有這些東西的意義。 在這里,您僅具有執行一件事且易於遵循的局部函數。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM