简体   繁体   中英

C# async await for pooling

I need to do some WebRequest to a certain endpoint every 2 seconds. I tried to do it with a Timer, the problem is that every call to the callback function is creating a different Thread and I'm havind some concurrence problems. So I decided to change my implementation and I was thinking about using a background worker with a sleep of two seconds inside or using async await but I don't see the advantages of using async await. Any advice? thank you.

This is the code that I will reimplement.

private void InitTimer()
{
    TimerCallback callback = TimerCallbackFunction;
    m_timer = new Timer(callback, null, 0, m_interval);
}

private void TimerCallbackFunction(Object info)
{
    Thread.CurrentThread.Name = "Requester thread ";
    m_object = GetMyObject();
}

public MyObject GetMyObject()
{
    MyObject myobject = new MyObject();

    try
    {
        MemoryStream responseInMemory = CreateWebRequest(m_host, ENDPOINT);
        XmlSerializer xmlSerializer = new XmlSerializer(typeof(MyObject));
        myObject = (MyObject) xmlSerializer.Deserialize(responseInMemory);
    }
    catch (InvalidOperationException ex)
    {
        m_logger.WriteError("Error getting MyObject: ", ex);
        throw new XmlException();
    }
    return myObject;
}

private MemoryStream CreateWebRequest(string host, string endpoint)
{
    WebRequest request = WebRequest.Create(host + endpoint);
    using (var response = request.GetResponse())
    {
        return (MemoryStream) response.GetResponseStream();
    }
}

EDIT: I have read this SO thread Async/await vs BackgroundWorker

async await is also concurrence. If you have concurrence problems and you want your application to have only one thread, you should avoid using async await.

However the best way to do WebRequest is to use async await, which does not block the main UI thread.

Use the bellow method, it will not block anything and it is recommended by Microsoft. https://msdn.microsoft.com/en-us/library/86wf6409(v=vs.110).aspx

private async  Task<MemoryStream> CreateWebRequest(string host, string endpoint)
{
    WebRequest request = WebRequest.Create(host + endpoint);
    using (var response = await request.GetResponseAsync())
    {
        return (MemoryStream)response.GetResponseStream();
    }
}

You don't mention what the concurrency problems are. It may be that the request takes so long that the next one starts before the previous one finishes. It could also be that the callback replaces the value in my_Object while readers are accessing it.

You can easily make a request every X seconds, asynchronously and without blocking, by using Task.Delay , eg:

ConcurrentQueue<MyObject> m_Responses=new ConcurrentQueue<MyObject>();
public async Task MyPollMethod(int interval)
{
    while(...)
    {
        var result=await SomeAsyncCall();
        m_Responses.Enqueue(result);
        await Task.Delay(interval);
    }
}

This will result in a polling call X seconds after the last one finishes.

It also avoids concurrency issues by storing the result in a concurrent queue instead of replacing the old value, perhaps while someone else was reading int.

Consumers of MyObject would call Dequeue to retrieve MyObject instances in the order they were received.

You could use the ConcurrentQueue to fix the current code too:

private void TimerCallbackFunction(Object info)
{
    Thread.CurrentThread.Name = "Requester thread ";
    var result=GetMyObject(); 
    m_Responses.Enqueue(result);
}

or

private async void TimerCallbackFunction(Object info)
{
    Thread.CurrentThread.Name = "Requester thread ";
    var result=await GetMyObjectAsync(); 
    m_Responses.Enqueue(result);
}

if you want to change your GetObject method to work asynchronously.

Since your request seems to take a long time, it's a good idea to make it asynchronous and avoid blocking the timer's ThreadPool thread while waiting for a network response.

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