문제

Im trying to write my first async app and ensure its working concurrently. The problem is i wrote the same app synchronously and i dont see a time difference.

class Program
{
 private static List<string> List1 = new List<string>();
 Stopwatch s = new Stopwatch();
    s.Start();      
    var waitOne = Load(1000);
 Task.WhenAll(waitOne);
  Console.WriteLine("Done Time:" + (s.ElapsedMilliseconds / 1000).ToString());
    Console.ReadLine();
}
    static async Task Load(int i)
{
    for (int y = 0; y < i; y++)
    {
        List1.Add(callWcf(y).Result);
    }

    await Task.Yield();
}
static async Task<string> callWcf(int i)
{
    string here;

    using (ServiceReference1.Client client = new AsyncTests.ServiceReference1.Client())
    {
        here = client.GetThisInt(i);
    }
    await Task.Yield();
    return here;

}
}

The WCF service is a simple service i built from this link http://msdn.microsoft.com/en-us/library/bb386386.aspx;

Returns "You entered {0}"

I did the same code synchronously and they both take 8 seconds for 1000 iterations, which is fast but i think my async is wrong as it should be faster that the synchronous. Ive followed tutorials, listened to a few podcasts and i know im missing something but i dont know what.

도움이 되었습니까?

해결책

I have an async intro you may find helpful.

Asynchronous code does not always run faster. In fact, a straight line-by-line translation to asynchronous code usually runs slower. The key benefit of asynchronous code is concurrency: it frees up the calling thread to do other work while the asynchronous operation is in progress.

To review your code:

Task.WhenAll(waitOne);

This doesn't actually do anything. WhenAll will return a Task that completes when waitOne completes, but then the task returned from WhenAll is ignored.

List1.Add(callWcf(y).Result);

Here your code stars an asynchronous operation (callWcf) and then turns around and immediately and synchronously blocks waiting for it to complete (Result).

await Task.Yield();

This code is pointless. Apparently it's only there to silence the compiler warnings about async methods not containing an await.

here = client.GetThisInt(i);

And here the code is synchronously blocking again.

As I describe in my async best practices article, one of the principles of async is to use "async all the way". It's easiest to do this from the lowest level (look for anything I/O-based) and work your way up. In this case, the best place to start is the WCF call:

static async Task<string> CallWcfAsync(int i)
{
  using (ServiceReference1.Client client = new AsyncTests.ServiceReference1.Client())
  {
    return await client.GetThisIntAsync(i);
  }
}

I also changed the method name to match the TAP conventions.

Next, you move to the caller(s) of that method:

static async Task Load(int i)
{
  for (int y = 0; y < i; y++)
  {
    List1.Add(await CallWcfAsync(y));
  }
}

or if you want to execute multiple calls simultaneously:

static async Task LoadAsync(int i)
{
  var tasks = Enumerable.Range(0, i).Select(y => CallWcfAsync(y));
  List1.AddRange(await Task.WhenAll(tasks));
}

Finally, your Main method does have to block on a task; this is one of the very rare situations where calling Result or Wait is permissible:

LoadAsync(1000).Wait();
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top