I want to know the simplest way to end asynchronous infinite looping.

Asked 2 years ago, Updated 2 years ago, 244 views

The proposed code is asynchronous, streaming via http communication to get json.

When the class Account to which the SetStreamTimeLine() function belongs is deleted, I would like the while statement in the Task.Run() and the StreamingHomeTimeLine_Async(this); internal infinite loop to be stopped. How do I implement this?As it is currently being implemented, is there any method like asynchronous processing?

I want to know how to implement an infinite loop-through process in a seemingly asynchronous way

The isStreamStop variable true allows you to implement actions to exit the infinite loop.

/*############################################################################################################################################
         * Timeline infinite loop
         * ###################################################################################################################*/
        public void setStreamTimeLine()
        {    
            Task.Run(async()=>
            { 
                while(isStreamStop==false)
                {
                    JsonData.StreamJsonjson=wait client.StreamingHomeTimeLine_Async(this);

                    Console.WriteLine(json.eventType);
                }

                Console.WriteLine("Finish";
            });
        }


        /*##################################################################################################################
         * Follow Timeline Streaming
        ###################################################################################################################*/
        public async Task<JsonData.StreamJson?>StreamingHomeTimeLine_Async (Account acc)
        {   
            var response = wait client.GetStreamAsync("https://"+instance+"/api/v1/streaming/user");
            var streamReader = new StreamReader (response);

           
            while(acc.isStreamStop==false)
            {
                var message = wait streamReader.ReadLineAsync();
                var eventType=message.Replace("event:", "");
                Console.WriteLine("eventType" + eventType);

                switch(eventType)
                {
                    case "update":
                    {
                        vardata=awit streamReader.ReadLineAsync();
                        data=data.Replace("data:", "");
                        varjson=JsonConvert.DeserializeObject<JsonData.Post>(data);

                        return new JsonData.StreamJson(JsonData.StreamJson.EventType.Update, json, null, null);
                    }
                    break;

                    case "notification":
                    {
                        vardata=awit streamReader.ReadLineAsync();
                        data=data.Replace("data:", "");
                        varjson=JsonConvert.DeserializeObject<JsonData.Notice>(data);

                        return new JsonData.StreamJson(JsonData.StreamJson.EventType.Notice, null, json, null);
                    }
                    break;

                    case "delete":
                    {
                        vardata=awit streamReader.ReadLineAsync();
                        data=data.Replace("data:", "");

                        return new JsonData.StreamJson(JsonData.StreamJson.EventType.Delete, null, null, data);
                    }
                    break;

                    default:
                    {
                    }
                    break;
                }
            }
            return new JsonData.StreamJson(JsonData.StreamJson.EventType.Invalid, null, null, null);

            // return null;
        }



        /*##################################################################################################################
         * Click the instance registration menu
        ###################################################################################################################*/
        private void Register_Click (object sender, EventArgse)
        {
            domain = new InputDomain_Form();
            domain.Show();

//                        Thread.Sleep (3000);
            Global.account[0].isStreamStop=true;
            Global.account.Remove (Global.account[0]);

        }

c#

2022-11-19 18:52

2 Answers

The correct answer is to use CancellationToken, which is also introduced by Dameo.
For this to work properly, CancellationToken must be passed across all asynchronous method calls.However, there is also an overload without CancellationToken, so even if I forget to give it to you, it won't cause a compilation error and it's hard to notice.Also, it's not good even if the synchronization call is mixed up.There are many other kinds of lice.

"I want to know how to do it simple," so I prepared a separate solution: keep Stream and Close and ReadAsync() will all fail and exceptions will be thrown outside while.

Stream activeStream;
public async Task <JsonData.StreamJson?>StreamingHomeTimeLine_Async(Account acc){   
    var response = wait client.GetStreamAsync("https://"+instance+"/api/v1/streaming/user");
    activeStream=response;
    ...
}

private void Register_Click (object sender, EventArgse) {
    domain = new InputDomain_Form();
    domain.Show();
    activeStream?.Close();
    Global.account.Remove (Global.account[0]);
}


2022-11-19 19:30

As Sayuri said, I will use CancellationToken.

The following is an example of a CancellationToken implementation:

public class account
{
    private CancellationTokenSource_cancellationTokenSource=new();
    
    public void Cancel()
    {
        _cancellationTokenSource.Cancel();
    }

    public void setStreamTimeLine()
    {    
        Task.Run(async()=>
        { 
            try
            {
                vartoken=_cancellationTokenSource.Token;
                while(true)
                {
                    token.ThrowIfCancellationRequested();
                    JsonData.StreamJsonjson=wait client.StreamingHomeTimeLine_Async(token);
                    Console.WriteLine(json.eventType);
                }
            }
            catch(OperationCancelledException)
            {
                Console.WriteLine("Cancelled.");
            }

            Console.WriteLine("Finish";
        });
    }
}
public async Task<JsonData.StreamJson?>StreamingHomeTimeLine_Async (CancellationToken)
{   
    :
    while(true)
    {
        token.ThrowIfCancellationRequested();
        var message = wait streamReader.ReadLineAsync().WaitAsync(token);
        :
//Thread.Sleep(3000);
Global.account[0].Cancel();
Global.account.Remove (Global.account[0]);

Most Async functions in .NET have CancellationToken as their argument, and they can cancel the wait, so they will cancel it as well.
Some are not supported, such as ReadLineAsycn(), but .NET6 allows you to cancel pseudo-cancel by setting it to ReadLineAsycn().WaitAsync(token).
Prior to .NET6, a different approach is required.Please refer to the following for details.
https://stackoverflow.com/questions/28626575/can-i-cancel-streamreader-readlineasync-with-a-cancellationtoken
By the way, ReadLineAsycn(token) is now available from .NET7.

"Also, it says ""when the account is deleted"", so I think it would be good to implement the IDisposable interface to finish the task."


2022-11-19 20:03

If you have any answers or tips


© 2024 OneMinuteCode. All rights reserved.