简体   繁体   中英

How to execute for loop only once in asyn method which continuously get event from eventhub

I tried with break inside my async method for loop but as getting events from event hub continuously it is calling method again and again.

I want to execute loop only once when get data == "mytestdata" .

If its true sending notification mail and need to break as i don't want to send again a mail because i have already send it.

I tried using isMailSend = true; too but it execute twic.

bool isMailSend = false;
async Task IEventProcessor.ProcessEventsAsync(PartitionContext context, IEnumerable<EventData> messages)
        {
            foreach (EventData eventData in messages)
            {
                string data = Encoding.UTF8.GetString(eventData.GetBytes());


                if (data == "mytestdata")
                {
                    //send mail notification
                isMailSend = true;
                Console.WriteLine("mail send ");
                break;
                }

                Console.WriteLine(string.Format("Message received.  Partition: '{0}', Data: '{1}'",
                    context.Lease.PartitionId, data));
            }

            //Call checkpoint every 1 minutes, so that worker can resume processing from 1 minutes back if it restarts.
            if (this.checkpointStopWatch.Elapsed > TimeSpan.FromMinutes(1))
            {
                await context.CheckpointAsync();
                this.checkpointStopWatch.Restart();
            }
        }

When your ProcessEventsAsync encounters the await, control is given back to its caller to see if the caller still can do something until the caller encounters the await, after which control goes up in the call stack to see if the caller has something to do, etc.

So your thread sees the await. One of your callers in the callstack is not awaiting, and calls ProcessEventsAsync. Although you have set isMailSent, you don't check it, and thus your foreach look is entered for the second time.

Change your code as follows:

class MyClass
{

    private bool isMailSent = false;

    async Task IEventProcessor.ProcessEventsAsync(PartitionContext context, IEnumerable<EventData> messages)
    {
        if (this.isMailSent)
        {
             // do whatever you want to do if a 2nd call is received
             // while isMailSent
             ProcessWhileIsMailSent(...)
        }
        else
        {   // called for the first time
            foreach (EventData eventData in messages)
            {
                string data = ...
                if (data == "mytestdata")
                {
                    this.isMailSent = true;
                // etc.

The effect is, that while isMailSent is true, and one of your callers decides to call you, your foreach is not called, but (in this example) ProcessWhileIsMailSent(...)

Don't forget to set isMailSent to false when you are ready to process received input again.

If you are multithreading consider locking isMailSent before accessing it.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM