2015-10-09 56 views
0

我的項目有MainForm中,我表現出F_Insert和設置的MdiParent爲MainForm的理念定時器與線程C#窗口形式

F_Insert f = new F_Insert(); 
f.MdiParent = this; 
f.Show(); 

在F_Insert,我把一個按鈕,單擊事件這樣

private void btn_Add_Click(object sender, EventArgs e) 
{ 
     //Insert data to SQL 
} 

此外,我想自動上傳從F_Insert插入的數據,每5秒

我使用System.Timer.Timer並將其設置爲MainForm_Load中的Thread

Thread t1 = new Thread(new ThreadStart(Timerss)); //In MainFormLoad event 
t1.Start(); 

public void Timerss() 
    { 
     System.Timers.Timer timer = new System.Timers.Timer(5000); 
     timer.Elapsed += Timer_Insert_Tick; 
     timer.AutoReset = true; 
     timer.Start(); 
    } 

private static void Timer_Insert_Tick(object sender, System.Timers.ElapsedEventArgs e) 
    { 
     //code auto upload data to server here 
     //Data get from Sql Local to upload SQL in Server 
    } 

問題是它不能正常工作。我感覺當我插入數據形式F_Insert時,數據受到定時器線程的影響,我開始在MainForm加載。

簡單的方式向你展示我的問題:當我分體式兩種工作(插入 和上傳)到2差的工作,它的工作好,它的意思是我 插入數據的完整,然後,我上傳數據,它會運作良好。 但是當我通過計時器的同時插入數據和數據自動上傳, 我看到一些錯誤:連接如SQL關閉或打開錯誤,沒有數據從F_Insert得到 ,有時它得到重複的數據(舊數據)

請給我一些這個問題的想法。對不起,但我是線程中的新手。謝謝 !!!

+0

什麼不起作用?你怎麼知道它不是?什麼錯誤?等等... – Enigmativity

+1

我在這裏看到的一個問題(它不是我清楚你的實際問題是)是唯一的引用計時器是在本地變量。我相信這意味着它可以並將被垃圾收集。 –

+0

嗨@Enigmativity,感謝您的收看!向我們展示我的問題的簡單方法是:當我將兩項工作(插入和上載)分成兩個不同的工作時,它工作良好,這意味着我插入數據完成,然後,我上傳數據,它將工作良好。但是,當我插入數據和數據自動上傳計時器在同一時間,我看到一些錯誤:連接sql關閉或打開錯誤,沒有數據從F_Insert獲取,有時得到重複的數據(舊數據)... – XCode2015

回答

0

那麼取決於你想要做什麼這個代碼應該被修改,但我希望它會給你的工作起點。

首先,讓我們創建靜態字段:

static volatile bool isDataChanged; 

關鍵字volatile使這個布爾線程安全的,這意味着這一領域始終保持最新的(因此正確的)值時,它是由任何線程訪問多線程環境)。

我們需要這個字段來保存稍後用來檢查數據是否被修改的bool值。

假設數據單擊事件處理程序中修改,我們應該將此標誌設置爲true:

private void btn_Add_Click(object sender, EventArgs e) 
{ 
     // Data is modified in UI thread 

     isDataChanged = true; 
} 

然後讓我們假設,在計時器滴答事件,我們應該的最新數據上傳至數據庫(數據位於UI線程,並且可以在兩個tick事件之間的時間跨度內改變)。

首先我們檢查數據是否有任何變化,如果沒有,我們只是退出該方法。如果修改完成了,我們需要將它們上傳到數據庫,爲了做到這一點,我們必須處理這樣一個事實,即定時器線程中的數據可能與我們UI線程中的數據不一樣。

讓我們創建一個本地變量,它將保存從UI線程獲取的正確數據,並使用this.Invoke()在UI線程上調用Func<object>委託。附加到委託的方法返回從UI線程檢索到的正確數據的實例,如object。我們明確地將其轉換爲我們數據的類型(通常是List<T>Dictionary<T1, T2>之類的集合類型之一),並使用此數據將其上載到數據庫。

之後,因爲我們在DB中的數據是正確的,我們將標誌isDataChanged更改爲false

private void Timer_Insert_Tick(object sender, System.Timers.ElapsedEventArgs e) 
{ 
    if(!isDataChanged) return; 

    // A very important line. It gets data from UI thread before uploading it 
    // Change DataType with your data Type and dataToUpload with data instance 

    DataType data = (DataType)this.Invoke(new Func<object>(() => dataToUpload)); 

    //use data to upload your data to server 

    isDataChanged = false; 
} 

P.S. 此外,最好將我們的定時器放在外部示波器中(因此可以從表格內的任何位置訪問)

public partial class MyForm : Form 
{ 
    ... 
    System.Timers.Timer timer; 

    public void Timerss() 
    { 
     timer = new System.Timers.Timer(5000); 
    } 

    ... 
} 
+0

謝謝,這是我的問題。我會盡力。非常感謝你使用 – XCode2015

+0

@ XCode2015它應該可以幫助你實現多線程,但是如果數據庫有問題,使用sql查詢或者數據處理的話 - 這完全是另一回事了 – Fabjan