2017-04-24 123 views
1

我遇到了在C#代碼中實現計時器的問題。我正在做什麼的高級別概述,我有一個WPF應用程序,基於數據饋送每三秒更新顯示給用戶的數據。窗口上的大多數數據每三秒鐘發生一次更改,但我試圖爲count執行SQL查詢,而我只希望數據每5分鐘更新一次。所以我建立了如下所示的SQL查詢和下面顯示的計時器,但計時器希望它是一個無效的時候,它必須返回一個字符串,我不知道如何克服這一點。在C#代碼中遇到問題

我在使用定時器(運行在我的主法)原嘗試:

Timer t = new Timer(TimeSpan.FromMinutes(5).TotalMilliseconds); // set the time (5 min in this case) 
      t.AutoReset = true; 
      t.Elapsed += new System.Timers.ElapsedEventHandler(SQLDataTotalCalls()); 
      t.Start(); 

我對SQL查詢方法:

public string SQLDataTotalCalls(object sender, ElapsedEventArgs a) 
{ 
    DateTime dte = DateTime.Today; 

    string fixedStartDate = String.Format("{0:yyyy-MM-dd " + "05:00:00.000" + "}", dte); 
    string fixedEndDate = String.Format("{0:yyyy-MM-dd " + "05:00:00.000" + "}", dte.AddDays(1)); 

    SqlConnection connection = null; 
    try 
    { 
     var dataSet = new DataSet(); 

     connection = new SqlConnection("Data Source=QL1OADB1;Initial Catalog=OADB;User Id=username;Password=password; 
     connection.Open(); 

     var command = new SqlCommand("SELECT COUNT(SOURCEID) AS 'MYCOUNT' " 
            + "FROM [OADB].[oadb].[CmsCallHistory] " 
            + "WHERE disposition = 2 and DISPSPLIT in (" + SkillNumber + ") AND SEGSTOP BETWEEN '" + fixedStartDate + "' and '" + fixedEndDate + "'", 
      connection) 
     { 
      CommandType = CommandType.Text 
     }; 

     var dataAdapter = new SqlDataAdapter { SelectCommand = command }; 

     dataAdapter.Fill(dataSet); 

     return dataSet.Tables[0].Rows[0]["MYCOUNT"].ToString(); 

    } 
    catch (Exception e) 
    { 
     throw new Exception(e.Message, e); 
    } 
    finally 
    { 
     if (connection != null) 
     { 
      connection.Close(); 
     } 
    } 
} 

更新:

每建議的答案如下,我已經將上面的內容更改爲:

async Task RunPeriodicQueryTotalCalls() 
{ 
    TimeSpan interval = TimeSpan.FromMinutes(5); 

    while (true) 
    { 
     await Task.Delay(interval); 

     string result = await Task.Run(SQLDataTotalCalls); 

     TotalDailyCalls = result; 
    } 
} 

我已經更新了我的方法的SQL查詢有這樣的聲明:

public string SQLDataTotalCalls() { ... } 

但我得到一個編譯器錯誤:

error CS0121: The call is ambiguous between the following methods or properties: 'Task.Run<TResult>(Func<TResult>)' and 'Task.Run(Func<Task>)'

+1

你想用這個字符串做什麼? – Steve

回答

2

假設C#會讓所需的簽名您訂閱您string -returning方法到void宣佈的事件。你認爲什麼樣的代碼實際上會得到那個回報值?你會在哪裏使用它?

在你的問題中沒有太多的上下文,這使得你很難(如果不是不可能的話)明確地理解你想要代碼做什麼。您的問題中沒有任何內容表明您將如何獲得返回的價值,也不知道您會如何處理這些價值。所有這一切,我認爲它可能會更好地使用任務並行庫API而不是定時器。這將允許您輕鬆地將返回值從後臺任務移動到UI線程,併爲您處理計時。

例如:

async Task RunPeriodicQuery() 
{ 
    TimeSpan interval = TimeSpan.FromMinutes(5); 

    while (true) 
    { 
     await Task.Delay(interval); 

     string result = await Task.Run((Func<string>)SQLDataTotalCalls); 

     // do something with "result" here...you'll be in the UI thread, so make it quick 
    } 
} 

在上面,你會從你的SQLDataTotalCalls()方法聲明中刪除參數。

您將需要調用方法RunPeriodicQuery()一次,在您的代碼的一部分,您正在初始化,否則將創建並啓動計時器。上面的實現使用inifite while (true)環,當然你可以介紹你要允許該方法退出任何機構,如果當你想讓它停止工作,如使用替代true一個bool場來控制循環操作。

如果這樣不能令人滿意地解決您的問題,請通過編輯來改進問題,使其包含一個很好的Minimal, Complete, and Verifiable code example,它清楚地顯示了您所嘗試的內容,準確解釋代碼的作用以及您希望執行的操作代替。

+0

遺憾的是缺乏細節。你的答案適合我試圖除了我在task.run,指出該呼叫收到一條錯誤消息做完全是以下方法或屬性之間曖昧:「Task.Run (Func鍵)」和「Task.Run( FUNC )」我並移除sQLDataTotalCalls()的參數 – firehotguitar88

+0

只是添加,如果我做的字符串結果=伺機task.run(sqldatatotalcalls()))我得到另一個錯誤信息,說明無法轉換初始化void類型到目標類型的字符串 – firehotguitar88

+0

我編輯了這個問題,這樣你就可以看到這個嘗試是如何工作的。 – firehotguitar88

2
  1. 您的代碼調用該方法,而不是將事件指向你的方法。

    //通知沒有括號,那是因爲你是在一個方法指向它,而不是在運行方法

    t.Elapsed + =新System.Timers.ElapsedEventHandler(SQLDataTotalCalls);

這樣做的一種簡單的方法是:

  t.Elapsed += SQLDataTotalCalls; 
  • 定時器應該僅被用於觸發一個事件,不返回值。委託(SQLDataTotalCalls)應該將字符串傳遞給其他對象或服務來保存字符串。

  • 你需要改變你的SQLDataTotalCalls方法的簽名返回void,所以它將匹配定時器處理