Reusable test code awaiting I / O
I am experimenting with using async / await on WCF exposed methods / services. Everything works fine, but I would like to simulate a service method waiting for I / O so that the service call is registered with the I / O completion port and the thread is pushed back to the thread pool.
To clarify, I'm just experimenting to validate the use of the I / O ports and get a better understanding of what is going on.
So, for example, my test service currently looks like this:
[ServiceContract]
public interface IHelloWorldService
{
[OperationContract]
Task<string> SayHello(string firstName, string lastName);
}
public class HelloWorldService : IHelloWorldService
{
public async Task<string> SayHello(string firstName, string lastName)
{
string str = string.Format("Hello {0} {1}", firstName, lastName);
return await Task.Factory.StartNew(() => str);
}
}
I would like to do something in SayHello () to make this code wait for some I / O, ideally a code pattern that I can copy / paste to use when I want to simulate waiting for I / O.
Typically Thread.Sleep () is used to simulate a long running task, but I'm pretty sure this will cause the thread pool thread to sleep and not start using the I / O completion port.
source to share
a code template that I can copy / paste to use in general when I want to simulate waiting for I / O.
Typically Thread.Sleep () is used to simulate a long running task
As mentioned in the comments, await Task.Delay(..)
is the asynchronous equivalent Thread.Sleep(..)
. It is commonly used to represent "unspecified asynchronous operation".
public async Task<string> SayHello(string firstName, string lastName)
{
await Task.Delay(TimeSpan.FromSeconds(2));
return string.Format("Hello {0} {1}", firstName, lastName);
}
However, if this is a test / mock stub, then you probably don't want to linger for a real amount of time. Asynchronous test stubs are usually implemented in sync with Task.FromResult
(or Task.FromException
or Task.FromCancelled
):
public Task<string> SayHello(string firstName, string lastName)
{
return Task.FromResult(string.Format("Hello {0} {1}", firstName, lastName));
}
But it looks like you want to force async. Note that this needs to be done in a unit test, but it comes up from time to time. To force async without wasting precious time, use Task.Yield
:
public async Task<string> SayHello(string firstName, string lastName)
{
await Task.Yield();
return string.Format("Hello {0} {1}", firstName, lastName);
}
source to share