如何从ElapsedEventHandler中调用异步方法

时间:2016-04-16 07:20:17

标签: c# time windows-services

我将定期使用Windows服务发送电报消息(每两分钟发送一次)。我的Windows服务启动正常,2分钟后停止。我检查了我的代码并发现它是因为异步。我该如何解决这个问题呢?

protected override void OnStart(string[] args)
{
    //< I declared a System.Timers.Timer to send new Telegram messages.
    aTimer = new System.Timers.Timer(120000); // 2 minutes
    aTimer.Elapsed += new ElapsedEventHandler(OnTimedEvent);
    aTimer.Enabled = true;

    GC.KeepAlive(aTimer);
    //>
}

private static void OnTimedEvent(object source, ElapsedEventArgs e)
{
    SendNewMessages();
}

async static void SendNewMessages()
{
    MyDataContext myDB = new MyDataContext();
    var newMessages = myDB.TelegramMessages.Where(tm => tm.Status != "New Message");

    foreach (TelegramMessage newMessage in newMessages)
    {
        try
        {
            var store = new FileSessionStore();
            var client = new TelegramClient(store, "MySession");
            await client.Connect();

            var res = await client.ImportContactByPhoneNumber(newMessage.ReceiverPhoneNumber);
            await client.SendMessage(res.Value, newMessage.Message);

            newMessage.Status = "Sent";
            myDB.SubmitChanges();
        }
        catch (Exception ex)
        {
            newMessage.Status = ex.Message;
            myDB.SubmitChanges();
        }

        Thread.Sleep(5000);
    }
}

1 个答案:

答案 0 :(得分:1)

我直接看到的一件事是async / await一直没有实现到eventhandler,因为&#34; SendNewMessages&#34;返回无效。而且你的事件处理程序不是异步的。

According to MSDN on "Async Return Types (C# and Visual Basic)"

  

void返回类型(Visual Basic中的Sub过程)的主要用途是在事件处理程序中,其中需要void返回类型。 void返回也可用于覆盖void返回方法或执行可归类为&#34; fire and forget的活动的方法。&#34;

这很可能是您的方案中的问题,因此您可以尝试将SendNewMessage更改为此

async static Task SendNewMessages()

你的事件处理程序

private async static void OnTimedEvent(object source, ElapsedEventArgs e)
{
    await SendNewMessages();
}

已更新

向您的&#34; SendNewMessages&#34; -method添加一些错误处理代码也是一个好主意,因为如果抛出异常,您的服务将会退出。

async static Task SendNewMessages()
{
    try
    {
    ... Your code here
    }
    catch(Exception e)
    {
    ... exceptionhandling here
    }
}

目前您只在foreach中进行异常处理,但您没有对数据库代码进行任何错误处理(据我所见)。

如果抛出异常

MyDataContext myDB = new MyDataContext();
var newMessages = myDB.TelegramMessages.Where(tm => tm.Status != "New Message");

foreach (TelegramMessage newMessage in newMessages)

或在这里:

newMessage.Status = ex.Message;
myDB.SubmitChanges();

服务将结束

相关问题