如何从ElapsedEventHandler调用异步方法 [英] How to Call an Async Method from within ElapsedEventHandler

查看:943
本文介绍了如何从ElapsedEventHandler调用异步方法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我要使用Windows服务来发送定期电报消息(每两分钟)。我的Windows服务启动罚款,被停止2分钟后。我检查了我的代码,并发现它是因为异步的。我怎样才能解决这个问题?



 保护覆盖无效的OnStart(字串[] args)
{
//<我宣布System.Timers.Timer发送新电报消息。
aTimer =新System.Timers.Timer(120000); //2分钟
aTimer.Elapsed + =新ElapsedEventHandler(OnTimedEvent);
aTimer.Enabled = TRUE;

GC.KeepAlive(aTimer);
//>
}

私有静态无效OnTimedEvent(对象源,ElapsedEventArgs E)
{
SendNewMessages();
}

异步静态无效SendNewMessages()
{
MyDataContext MYDB =新MyDataContext();
VAR newMessages = myDB.TelegramMessages.Where(TM =>!tm.Status =新邮件);

的foreach(TelegramMessage NewMessage作为在newMessages)
{

{
变种店=新FileSessionStore();
VAR的客户=新TelegramClient(店MySession的);
等待client.Connect();

VAR解析度=等待client.ImportContactByPhoneNumber(newMessage.ReceiverPhoneNumber);
等待client.SendMessage(res.Value,newMessage.Message);

newMessage.Status =已发送;
myDB.SubmitChanges();
}
赶上(异常前)
{
newMessage.Status = ex.Message;
myDB.SubmitChanges();
}

Thread.sleep代码(5000);
}
}


解决方案

一我直接看到的是异步/伺机尚未一路以来SendNewMessages落实到事件处理程序返回void。和你的事件处理程序是不是异步。



根据MSDN上的异步返回类型(C#和Visual Basic)




的主要用途虚空返回类型(在Visual Basic Sub过程)是在事件处理程序,在需要返回void类型。返回void也可以用来覆盖无效返回方法或者用于执行可归类为活动办法发射后不管。




这是最有可能在您的情况的问题,所以你可以尝试改变你SendNewMessage这个

 异步静态任务SendNewMessages ()

和您的事件处理这个

 专用异步静态无效OnTimedEvent(对象源,ElapsedEventArgs E)
{
等待SendNewMessages();
}



更新时间:



这也将是一个好主意,一些ErrorHandling中的代码添加到您的SendNewMessages-method因为如果抛出一个异常,您的服务将退出。

 异步静态任务SendNewMessages()
{

{
...您的代码在这里
}
赶上(例外五)
{
...这里exceptionhandling
}
}

目前你只有你的foreach内exceptionhandling,但你没有任何ErrorHandling中(据我可以看到),为你的数据库的代码。



如果一个例外是扔在这里。

  MyDataContext MYDB =新MyDataContext(); 
VAR newMessages = myDB.TelegramMessages.Where(TM =>!tm.Status =新邮件);

的foreach(TelegramMessage NewMessage作为在newMessages)

或此:

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



该服务将结束


I'm going to use a Windows Service to send Telegram Messages periodically (Every two minutes). My Windows Service starts fine and after 2 minutes it is stopped. I checked my code and find out it is because of async. How can I solve the problem?

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);
    }
}

解决方案

One thing I see directly is that async/await has not been implemented all the way to the eventhandler since "SendNewMessages" returns void. And your eventhandler is not async.

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

The primary use of the void return type (Sub procedures in Visual Basic) is in event handlers, where a void return type is required. A void return also can be used to override void-returning methods or for methods that perform activities that can be categorized as "fire and forget."

This is most likely an issue in your scenario, so you could try changing your SendNewMessage to this

async static Task SendNewMessages()

And your eventhandler to this

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

UPDATED

It would also be a good idea to add some errorhandling code to your "SendNewMessages"-method since if an exception is thrown, your service will quit.

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

At the moment you only have exceptionhandling within your foreach, but you do not have any errorhandling (as far as I can see) for your database-code.

if an exception is throw here

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

foreach (TelegramMessage newMessage in newMessages)

or here:

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

The service would end

这篇关于如何从ElapsedEventHandler调用异步方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆