簡體   English   中英

在c#中使用線程工作的最佳方法是什么?

[英]What is the best way to thread work in c#?

在c#中使用線程工作(方法)的最佳方法是什么?

例如:

假設我有一個表單,並希望從db加載數據。

My form controls: 
 - dataGridView (to show data from DB), 
 - label (loading status) and 
 - button (start loading).

當我單擊按鈕時,我的表單將被凍結,直到任務完成。 在任務完成之前,加載狀態也不會改變。 我認為異步線程會是答案嗎?

所以我的問題是:處理這個問題的最佳方法是什么? 我知道有很多關於線程的東西,但是它們之間的區別是什么?你如何使線程安全?

你是如何解決這類問題的?

最好的祝福。

如果使用Windows窗體,則應查看BackrgroundWorker 更一般地說,使用ThreadPool類通常很有用。 最后,值得一看的是新的.NET 4的Parallel類。

沒有通用的“最佳”方式來處理工作。 你只需要嘗試不同的做事方式,我擔心。

我特別喜歡Jeremy D. Miller 在本頁描述的延續思想(向下滾動以找到“延續”部分)。 它非常優雅,意味着編寫非常少的樣板代碼。

基本上,當您使用Func參數調用“ExecuteWithContinuation”時,該函數將異步執行,然后在完成時返回一個操作。 然后將操作編組回您的UI線程以充當延續。 這允許您快速將操作拆分為兩位:

  1. 執行不應阻止UI的長時間運行操作
  2. ...完成后,更新UI線程上的UI

需要一點時間來適應,但它很酷。

public class AsyncCommandExecutor : ICommandExecutor
{
    private readonly SynchronizationContext m_context;

    public AsyncCommandExecutor(SynchronizationContext context)
    {
        if (context == null) throw new ArgumentNullException("context");
        m_context = context;
    }

    public void Execute(Action command)
    {
        ThreadPool.QueueUserWorkItem(o => command());

    }

    public void ExecuteWithContinuation(Func<Action> command)
    {
        ThreadPool.QueueUserWorkItem(o =>
                                         {
                                             var continuation = command();
                                             m_context.Send(x => continuation(), null);
                                         });
    }
}

然后你就這樣使用它(原諒格式......)

public void DoSomethingThatTakesAgesAndNeedsToUpdateUiWhenFinished()
{
    DisableUi();
    m_commandExecutor.ExecuteWithContinuation(
                () =>
                    {
                        // this is the long-running bit
                        ConnectToServer();

                        // This is the continuation that will be run
                        // on the UI thread
                        return () =>
                                    {
                                        EnableUi();
                                    };
                    });
}

你可以使用這種模式: -

    private void RefreshButton_Click(object sender, EventArgs e)
    {
        MessageLabel.Text = "Working...";
        RefreshButton.Enabled = false;

        ThreadPool.QueueUserWorkItem(delegate(object state)
        {
            // do work here 
            // e.g. 
            object datasource = GetData();
            this.Invoke((Action<object>)delegate(object obj)
            {
                // gridview should also be accessed in UI thread 
                // e.g. 
                MyGridView.DataSource = obj;

                MessageLabel.Text = "Done.";
                RefreshButton.Enabled = true;
            }, datasource);
        });
    }

您無法從分離線程中運行的代碼訪問您的控件 - 框架不允許這樣做,這解釋了您獲得的錯誤。

您需要在非表單對象中緩存從db檢索的數據,並在后台工作線程完成后使用該對象的數據填充UI(並處理訪問該對象的同步)。

暫無
暫無

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

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