2017-04-24 120 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,所以它将匹配定时器处理