1. 程式人生 > >c#執行非同步操作

c#執行非同步操作

Winform中的控制元件是繫結到特定的執行緒的(一般是主執行緒),這意味著從另一個執行緒更新主執行緒的控制元件不能直接呼叫該控制元件的成員。

控制元件繫結到特定的執行緒這個概念如下:

為了從另一個執行緒更新主執行緒的Windows Form控制元件,可用的方法有:

首先用一個簡單的程式來示例,這個程式的功能是:在Winfrom窗體上,通過多執行緒用label顯示時間。給出下面的兩種實現方式

1.結合使用特定控制元件的如下成員                                            

InvokeRequired屬性:返回一個bool值,指示呼叫者在不同的執行緒上呼叫控制元件時是否必須使用Invoke()方法。如果主調執行緒不是建立該控制元件的執行緒,或者還沒有為控制元件建立視窗控制代碼,則返回true。

Invoke()方法:在擁有控制元件的底層視窗控制代碼的執行緒上執行委託。

BeginInvoke()方法:非同步呼叫Invoke()方法。

EndInvoke()方法:獲取BeginInvoke()方法啟動的非同步操作返回值。

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace MutipleThreadTest
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }
     

        public delegate void ChangeTimeDelegate(Control c);//包裝代理類

        private void PrintTime()
        {
            if (label1.InvokeRequired == true)
            {
                
                while (true)
                {
                  label1.Invoke(new ChangeTimeDelegate((Control c)=> c.Text = DateTime.Now.ToString() ) , 
                  new object[] {label1});
                }
            }
            else
                while (true)
                {
                    label1.Text = DateTime.Today.ToString();
                }
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            Thread t = new Thread(new ThreadStart(PrintTime));
            t.IsBackground = true;
            t.Start(); 
        }

        
    }
}
還可以使用backegroundworker控制元件
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace MutipleThreadTest
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }
     

        public delegate void ChangeTimeDelegate(Control c);

        private void Form1_Load(object sender, EventArgs e)
        {
            backgroundWorker1.RunWorkerAsync();
        }

        private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
        {
            if (label1.InvokeRequired == true)
            {

                while (true)
                {
                        label1.Invoke(new ChangeTimeDelegate((Control c) => c.Text = DateTime.Now.ToString())
                        , new object[] { label1 });
                }
            }
            else
                while (true)
                {
                    label1.Text = DateTime.Today.ToString();
                }
        }
    }
}

更新另一個執行緒的進度條示例(第一種方法實現)                             

DebugLZQ覺得第一種方法要更直觀一點,或是更容易理解一點。下面再用第一種方法來做一個Demo:輸入一個數,多執行緒計算其和值更新介面上的Label,並用進度條顯示計算的進度。實際上就是,更新另一個執行緒的兩個UI控制元件。

原部落格使用的是new 一個執行緒實現的,這裡我是用backgroundworker元件實現

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace MutipleThreadTest
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }
     

        public delegate void ChangeProgressDelegate(ProgressBar c,int s);
        public delegate void ChangeLabelDelegate(Control c, string s);
     

        private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
        {
            long num = Convert.ToInt64(e.Argument);
            long sum = 0;
            for(long i = 1; i <= num; i++)
            {
                sum += i;
                if(i % 100 == 0)
                {
                    
                        progressBar1.Invoke(new ChangeProgressDelegate((ProgressBar c,int s) => c.Value = s),
                        new object[] { progressBar1, Convert.ToInt32((i * 100) / num) });
                    
                }
                
                
            }
            label1.Invoke(new ChangeLabelDelegate((Control c, string s) =>
            {
                c.Text = s;
            }), new object[] { label1, sum.ToString() });
        }

        private void button1_Click(object sender, EventArgs e)
        {
            backgroundWorker1.RunWorkerAsync(textBox1.Text);
        }

        private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            progressBar1.Value = 0;
            textBox1.Text = "";
        }
    }
}

總覺得這樣更新一個元件太麻煩了,又是代理程序的。不知道還有沒有更好的辦法。繼續研究一下


相關推薦

c#執行非同步操作

Winform中的控制元件是繫結到特定的執行緒的(一般是主執行緒),這意味著從另一個執行緒更新主執行緒的控制元件不能直接呼叫該控制元件的成員。 控制元件繫結到特定的執行緒這個概念如下: 為了從另一個執行緒更新主執行緒的Windows Form控制元件,可用的方

C#執行非同步操作的幾種方式比較和總結

原文地址:http://www.cnblogs.com/durow/p/4826653.html 轉載此文的目的就是想讓自己記住曾經尋找過這些資料 感謝這位博主的無私奉獻 0x00 引言 之前寫程式的時候在遇到一些比較花時間的操作例如HTTP請求時,總是會new一

C# 執行緒知識--使用Task執行非同步操作

 在C#4.0之前需要執行一個複雜的非同步操作時,只能使用CLR執行緒池技術來執行一個任務。執行緒池執行非同步任務時,不知道任務何時完成,以及任務的在任務完成後不能獲取到返回值。但是在C#4.0中引人了一個的任務(System.Threading.Tasks名稱空間的型別

BroadcastReceiver 使用goAsync 執行非同步操作

BroadcastReceiver 生命週期 一個BroadcastReceiver 物件只有在被呼叫onReceive(Context, Intent)的才有效的,當從該函式返回後,該物件就無效的了,結束生命週期。 因此從這個特徵可以看出,在所呼叫的onReceive(C

C#】C#執行緒_I/O限制的非同步操作

目錄結構: contents structure [+] 為什麼需要非同步IO操作 C#的非同步函式 async和await的使用 非同步函式的狀態機 非同步函式如何轉化為狀態機 如何擴充套件非

C#多執行緒程式設計筆記(5.5)-處理非同步操作中的異常

近來在學習Eugene Agafonov編寫的《C#多執行緒程式設計實戰》(譯),做些筆記也順便分享一下^-^本篇將描述在C#中使用非同步函式時如何處理異常。我們將學習對多個並行的非同步操作使用await時如何聚合異常。using System; using System.T

C++11學習筆記-----獲取非同步操作執行結果

在多執行緒環境中,不管是傳遞lambda還是傳遞函式指標,再或者是傳遞函式物件給std::thread,都很難獲取執行函式返回值。在以前,只能將結果以引用的形式作為執行緒函式引數的一部分以此儲存返回值,但是仍然存在很大侷限性,甚至不太美觀。C++11引入的std

《CLR Via C#》讀書筆記:27.計算限制的非同步操作

一、CLR 執行緒池基礎 一般來說如果計算機的 CPU 利用率沒有 100% ,那麼說明很多程序的部分執行緒沒有執行。可能在等待 檔案/網路/資料庫等裝置讀取或者寫入資料,又可能是等待按鍵、滑鼠移動等事件。 執行 I/O 限制的操作時,作業系統通過裝置驅動程式通知硬體幹活,而 CPU 處於一種空閒狀態。而

2017.10.20 C#跨執行操作控制元件的執行緒安全方法

C#跨執行緒操作控制元件的執行緒安全方法 在C#中,經常用到這樣一個場景,Windows Form程式啟動一個工作者執行緒執行一部分工作,這樣做是為了避免速度慢的工作如果直接呼叫會使得主Form停止響應一段時間。 既然啟動了執行緒,就避免不了執行緒之間資料傳遞的事情,相信你有很多種辦法

執行非同步操作日誌

上次寫的一篇部落格,多執行緒非同步操作日誌不完整,現在寫一個完整的 功能是:使用者訪問一個controller,將訪問的記錄儲存到佇列中去,在開啟定時器,消費掉記錄儲存到檔案中(可改為儲存到資料庫) 我的idea目錄: controller中的程式碼: package com.

C# 多執行緒學習系列四之取消、超時子執行操作

1、簡介 雖然ThreadPool、Thread能開啟子執行緒將一些任務交給子執行緒去承擔,但是很多時候,因為某種原因,比如子執行緒發生異常、或者子執行緒的業務邏輯不符合我們的預期,那麼這個時候我們必須關閉它,而不是讓它繼續執行,消耗資源.讓CPU不在把時間和資源花在沒有意義的程式碼上.  

c#winform跨執行操作控制元件的一種方法,InvokeRequired

  在winform裡面如果有建立新執行緒的話,線上程裡面直接操作控制元件或修改控制元件的屬性是不允許的,雖然有辦法讓程式執行時忽略跨執行緒可能產生的問題,從而解決;但是從科學的角度看,該辦法並不可取,所以我就用了InvokeRequired的辦法解決跨執行緒操作問題。  

c#多執行操作測試(阻塞執行緒,結束任務)

using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Te

ajax非同步上傳檔案完成後執行其他操作

var fileCount=檔案個數;//計數器 $.ajax({             //寫死測試             url: baseUrl + "/dfs/upload/plugins/fileproxy/fileproxy?type=upload&

C# 定時關窗 & 跨執行操作視窗

新增定時器 直接在程式碼中new一個定時器並繫結回撥函式即可 跨執行緒關閉其他視窗 會報異常: 解決方法: 在你要操作的視窗的類的建構函式中指明允許跨執行緒操作。 public partia

ES6非同步操作概述- 單執行緒模型

單執行緒模型 單執行緒模型指的是,JavaScript 只在一個執行緒上執行。也就是說,JavaScript 同時只能執行一個任務,其他任務都必須在後面排隊等待。 注意,JavaScript 只在一個執行緒上執行,不代表 JavaScript 引擎只有一個執行緒。事實上,

常用程式碼整理:執行非同步操作

說明:大部分內容都是參考別的文章,這裡做整理是為了以後的程式設計有實用的模板,可以即需即用。 1、倒計時 public class RegisterActivity extends BaseActivi

c++ 執行緒併發、任務佇列、非同步 任務封裝和分發 lambda與任務 boost

在開發C++程式時,一般在吞吐量、併發、實時性上有較高的要求。設計C++程式時,總結起來可以從如下幾點提高效率: 併發非同步快取 下面將我平常工作中遇到一些問題例舉一二,其設計思想無非以上三點。 1任務佇列 1.1    以生產者-消費者模型設計任務佇列    

C# 多執行操作介面時,使用Invoke與BeginInvoke的區別

Invoke方法的引數很簡單,一個委託,一個引數表(可選),而Invoke方法的主要功能就是幫助你在 UI執行緒(即建立控制元件的執行緒)上呼叫委託所指定的方法。Invoke方法首先檢查發出呼叫的執行緒(即當前執行緒)是不是UI執行緒,如果是,直接執行委託指向 的方法

現在有多個非同步操作ajax請求,我們需要當所有非同步請求都成功的時候,執行後續操作

1》場景: 現在有多個非同步操作ajax請求,我們需要當所有非同步請求都成功的時候,執行後續操作 2》方法 方法一:通常的講,我們可以設定一個flag變數,然後在各自的ajax的成功回撥內去維護這個變數數量,當滿足條件時,我們來觸發後續函式 方法二: jq的$.wh