I would like to use the Task framework in .NET to schedule something to run on a different thread then when it's done continue with an operation to update the UI on the UI thread. (I haven't played with it much yet, so it's not very familiar to me.)
Here is the code:
Task<List<NewsItem>> fetchTask = new Task<List<NewsItem>>(() =>
{
List<NewsItem> items = Rss.FetchNewsItems(feed);
return items;
}).ContinueWith(x => UpdateNewsItems(x.Result),CancellationToken.None,TaskContinuationOptions.None,scheduler);
private void UpdateNewsItems(List<NewsItem> items)
{
...
}
Cannot implicitly convert type 'System.Threading.Tasks.Task' to 'System.Threading.Tasks.Task<System.Collections.Generic.List<Spark.Models.NewsItem>>'. An explicit conversion exists
I thought that if I use the generic signature of List<NewsItem> on the task that the Task.Result would return that type so I could pass it to my method...
What am I doing wrong here?
The issue is that since your lambda is an Action<Task>, ContinueWith returns a Task, and you are assigning that to fetchTask, which is of type Task<List<NewsItem>>. Note that you are assigning the result of the ContinueWith call to the variable, not the result of the new Task<> call.
If you do something like this:
var fetchTask =
new Task<List<NewsItem>>(() =>
{
List<NewsItem> items = Rss.FetchNewsItems(feed);
return items;
})
.ContinueWith<List<NewsItem>>(
x => UpdateNewsItems(x.Result),
CancellationToken.None,
TaskContinuationOptions.None,scheduler);
you will notice that there's a problem becuase your lambda returns void, but the task expects a return of List<NewsItem>. So you probably want to either return that from your UpdateNewsItems, or create the task and add the continuation later.
Related
I'm trying to pass HttpContext.Current to the thread created via Task.Run. As I have a Transaction ID in in HttpContext.Items, which I'll need in the thread.
public static Task<TResult> RunWithContext<TResult>(Func<TResult> function)
{
var context = HttpContext.Current;
return Task.Run(()=> { RequestHelper.SaveHttpContextInThread(context); return function(); } );
}
public static void SaveHttpContextInThread(HttpContext context)
{
Thread.SetData(Thread.GetNamedDataSlot(RequestHelper.THREAD_SLOT_NAME), context);
}
var response = TaskHelper.RunWithContext(() => _service.UpdateJob(jobjsonstring));
var jobData = JObject.Parse(response.Result); //Compiler error here
But a compiler error
'Argument 1: cannot convert from 'System.Threading.Tasks.Task'
to 'string'
occurs in the last line.
Seems to be an issue with the way I'm returning from the anonymous method.
Update
It seems _service.UpdateJob was returning Task but I was expecting it to return Job object, Apologies.
Actual Problem: In a WebAPI we want to run some task in a new thread. There is a value TransactionID in HttpContext.Items. We want the newly created thread to be able to read TransactionID. The above approach was to pass the entire HttpContext to the new thread.
It can get quite confusing with the nested use of tasks, especially without the use async/await.
The _service.UpdateJob(jobjsonstring) returns a Task. Therefore Task.Run which executes this function returns a Task object with a Task as result.
In order to get the Result of the _service.UpdateJob call you have to use response.Result.Result.
var jobData = JObject.Parse(response.Result.Result);
Another alternative (without async/await) is to return the Result inside the function, e.g.
var response = TaskHelper.RunWithContext(() => _service.UpdateJob(jobjsonstring).Result);
This method is called from wpf main thread.
Throwing - Cannot implicitly convert type 'bool' to 'System.Threading.Tasks.Task' error.
What am I doing wrong?
DocCollection is of type ObservableCollection.
Task TaskProcesQueue(SynchronizationContext _SyncContext)
{
return Task.Run(() =>
{
if (DocCollection != null)
{
foreach (var item in DocCollection.ToList())
{
ProcessCurrentDocument(item);
var t = Task.Run(() => DocCollection.Remove(item), _SyncContext));
}
}
});
}
Task.Run has no overload accepting a SynchronizationContext. Hence, when overload resolution kicks in, it fails to find the appropriate overload. If you remove the synchronization context, it compiles:
var t = Task.Run(() => DocCollection.Remove(item));
Note i'd advise you not to use a dedicated threadpool thread to remove an item from a collection. That seems redundant. Instead, let the thread-pool thread already dedicated to removing items to it's job:
while (DocCollection.Count > 0)
{
ProcessCurrentDocument(item);
DocCollection.Remove(item);
}
Edit:
If you want to post on the SynchronizationContext:
_SyncContext.Post(_ => { DocCollection.Remove(item) }, null);
Now that your code is in sync, your problem is that DocCollection.Remove(item) is actually returning true/false, being a boolean method that indicates whether or not the remove succeeded or not.
If you'll remove that whole line, all will work nicely, and items will be processed (but not removed).
I think what you want is to actually use the Result of the running the task (note that it'll block though).
Have a look at the official page on MSDN for more.
I am working with a library for which I do not have the source, and as such I can't decorate it with the async keyword and do things like await a Task (at least I don't know how to do that). It exposes a method which returns an object (I'll call it "answer") and takes an integer, and a parameter of type Action where I retrieve that answer. How can I wait for answer to get populated before my code continues?
Object answer = null;
remoteLibrary.remoteMethod(42, x =>
{
answer = x.Value; //This might take a few seconds
});
//I want to do something here with "answer" AFTER it has been populated
You need a synchronization construct. And since this can take a few seconds it would be a waste to use a synchronous (blocking) one so I suggest an asynchronous one like TaskCompletionSource:
var tcs = new TaskCompletionSource<object>();
remoteLibrary.remoteMethod(42, x =>
{
tcs.SetResult(x.Value);
});
var answer = await tcs.Task;
// use answer
The TaskCompletionSource exposes a task that you can await that wouldn't complete until you call SetResult (or SetCanceled, SetException). When it completes you get the result you set in SetResult so you don't need the dummy variable anymore.
It is an asynchronous method that goes and queries the database and sometime returns.
Currently It is something like this:
this.Model.GetStudentKeys(keysList);
this.Foo1();
this.Foo2();
I am not proficient with the syntax but what I need to have is to change the code above in a way that those two Foo methods get called after the Async query is done. So I kind of know I need something like this:
this.Model.GetStudentKeys(keysList, callBack);
Action<object> callback {
this.Foo1();
this.Foo2();
}
But like I said I am not familiar with the syntax. Can you please help me with it?
You can use callbacks, but they are being superseded by C#'s async/await syntax. Before I explain said syntax however, I'll show you how you can achieve the same with Actions:
/*Action is a reference type, so its assignment is no different. Its value is a lambda
expression (http://msdn.microsoft.com/en-us/library/bb397687.aspx),
which you can think of as an anonymous method.*/
private Action<object> callback = o =>
{
object result = o;
this.Foo1();
this.Foo2();
};
/*It's good practice in C# to append 'Async' to the name of an asynchronous method
in case a synchronous version is implemented later.*/
this.Model.GetStudentKeysAsync(keysList, callback);
With this approach, your GetStudentsAsync method must invoke the callback, like so:
public void GetStudentsAsync(List<string> keys, Action<object> callback)
{
var returnValue = null;
//do some stuff...
callback(returnValue);
}
You can also pass the lambda expression directly as a parameter:
this.Model.GetStudentKeysAsync(keysList, o =>
{
this.Foo1();
this.Foo2();
});
With .NET 4.5 (and .NET 4.0 using the Microsoft Async package) however, you can use the async and await keywords provided by C# 5:
//notice the 'async' keyword and generic 'Task(T)' return type
public async Task<IEnumerable<StudentModel>> GetStudentsAsync(IEnumerable<int> keyList)
{
/*to invoke async methods, precede its invocation with
the 'await' keyword. This allows program flow to return
the line on which the GetStudentsAsync method was called.
The flow will return to GetStudentsAsync once the database
operation is complete.*/
IEnumerable<StudentModel> students = await FakeDatabaseService.ExecuteSomethingAsync();
return students;
}
Simply invoke the above method as follows:
IEnumerable<StudentModel> students = await this.Model.GetStudentsAsync(keyList);
You can define your function like that
void GetStudentKeys(keysList, Func<bool> callback)
{
Thread th = new Thread(delegate(){
//do some work in separate thread and inside that thread call
if(callback != null)
callback();
});
th.Start();
}
and change the function call to
this.Model.GetStudentKeys(keysList, () => {
this.Foo1();
this.Foo2();
return true;
});
Something like that.
Assuming the GetStudentKeys method returns a Task object (due to it being async), you could use the (new in C# 5.0) construct async and await,
public async void MethodName()
{
await this.Model.GetStudentKeysAsync(keysList); // <-- Async operation
this.Foo1();
this.Foo2();
}
Once the async operation completes, the code will then continue after the await keyword.
The following code compiles and runs well. But where is the return statement for the Consumer() and Producer() methods?
class Program
{
static BufferBlock<Int32> m_buffer = new BufferBlock<int>(
new DataflowBlockOptions { BoundedCapacity = 10 });
public static async Task Producer() <----- How is a Task object returned?
{
while (true)
{
await m_buffer.SendAsync<Int32>(DateTime.Now.Second);
Thread.Sleep(1000);
}
}
public static async Task Consumer() <----- How is a Task object returned?
{
while (true)
{
Int32 n = await m_buffer.ReceiveAsync<Int32>();
Console.WriteLine(n);
}
}
static void Main(string[] args)
{
Task.WaitAll(Consumer(), Producer());
}
}
While your question states the obvious - the code compiles - and the other answers try to explain-by-example, I think the answer is best described in the following two articles:
"Above-the-surface" answer - full article is here: http://msdn.microsoft.com/en-us/magazine/hh456401.aspx
[...] C# and Visual Basic [...] giving enough hints to the compilers
to build the necessary mechanisms for you behind the scenes. The
solution has two parts: one in the type system, and one in the
language.
The CLR 4 release defined the type Task [...] to represent the
concept of “some work that’s going to produce a result of type T in
the future.” The concept of “work that will complete in the future but
returns no result” is represented by the non-generic Task type.
Precisely how the result of type T is going to be produced in the
future is an implementation detail of a particular task; [...]
The language half of the solution is the new await keyword. A regular
method call means “remember what you’re doing, run this method until
it’s completely finished, and then pick up where you left off, now
knowing the result of the method.” An await expression, in contrast,
means “evaluate this expression to obtain an object representing work
that will in the future produce a result. Sign up the remainder of the
current method as the callback associated with the continuation of
that task. Once the task is produced and the callback is signed up,
immediately return control to my caller.”
2.The under-the-hood explanation is found here: http://msdn.microsoft.com/en-us/magazine/hh456403.aspx
[...] Visual Basic and C# [...] let you express discontinuous
sequential code. [...] When the Visual Basic or C# compiler gets hold
of an asynchronous method, it mangles it quite a bit during
compilation: the discontinuity of the method is not directly supported
by the underlying runtime and must be emulated by the compiler. So
instead of you having to pull the method apart into bits, the compiler
does it for you. [...]
The compiler turns your asynchronous method into a statemachine. The
state machine keeps track of where you are in the execution and what
your local state is. [...]
Asynchronous methods produce Tasks. More specifically, an asynchronous
method returns an instance of one of the types Task or Task from
System.Threading.Tasks, and that instance is automatically generated.
It doesn’t have to be (and can’t be) supplied by the user code. [...]
From the compiler’s point of view, producing Tasks is the easy part.
It relies on a framework-supplied notion of a Task builder, found in
System.Runtime.CompilerServices [...] The builder lets the compiler
obtain a Task, and then lets it complete the Task with a result or an
Exception. [...] Task builders are special helper types meant only for
compiler consumption. [...]
[...] build up a state machine around the production and consumption
of the Tasks. Essentially, all the user logic from the original method
is put into the resumption delegate, but the declarations of locals
are lifted out so they can survive multiple invocations. Furthermore,
a state variable is introduced to track how far things have gotten,
and the user logic in the resumption delegate is wrapped in a big
switch that looks at the state and jumps to a corresponding label. So
whenever resumption is called, it will jump right back to where it
left off the last time.
when the method has no return statement its return type is Task. Have a look at the MSDN page of Async Await
Async methods have three possible return types: Task<TResult>, Task, void
if you need a Task you must specify the return statement. Taken from the MSDN page:
// TASK<T> EXAMPLE
async Task<int> TaskOfT_MethodAsync()
{
// The body of the method is expected to contain an awaited asynchronous
// call.
// Task.FromResult is a placeholder for actual work that returns a string.
var today = await Task.FromResult<string>(DateTime.Now.DayOfWeek.ToString());
// The method then can process the result in some way.
int leisureHours;
if (today.First() == 'S')
leisureHours = 16;
else
leisureHours = 5;
// Because the return statement specifies an operand of type int, the
// method must have a return type of Task<int>.
return leisureHours;
}
async keyword kind of tells compiler that the method body should be used as a Task body. In simple way we can say that these are equivalents to your examples:
public static Task Producer() <----- How is a Task object returned?
{
return Task.Run(() =>
{
while (true)
{
m_buffer.SendAsync<Int32>(DateTime.Now.Second).Wait();
Thread.Sleep(1000);
}
});
}
public static Task Consumer() <----- How is a Task object returned?
{
return Task.Run(() =>
{
while (true)
{
Int32 n = m_buffer.ReceiveAsync<Int32>().Wait();
Console.WriteLine(n);
}
});
}
Of course the compiled result of your methods will be completely different from my examples, because compiler smart enough and it can generate code in such way, so some of the lines in your method will be invoked on the context (thread), which calls the method and some of them on the background context. And this is actually why Thread.Sleep(1000); is not recommended in the body of async methods, because this code can be invoked on the thread, which calls this method. Task has equivalent which can replace Thread.Sleep(1000); the equivalent await Task.Delay(1000), which will be invoked on background thread. As you can see await keyword guaranties you that this call will be invoked on the background context and will not block the caller context.
Let's take a look on one more example:
async Task Test1()
{
int a = 0; // Will be called on the called thread.
int b = await this.GetValueAsync(); // Will be called on background thread
int c = GetC(); // Method execution will come back to the called thread again on this line.
int d = await this.GetValueAsync(); // Going again to background thread
}
So we can say that this will be generated code:
Task Test1()
{
int a = 0; // Will be called on the called thread.
vat syncContext = Task.GetCurrentSynchronizationContext(); // This will help us go back to called thread
return Task.Run(() =>
{
// We already on background task, so we safe here to wait tasks
var bTask = this.GetValueAsync();
bTask.Wait();
int b = bTask.Result;
// syncContext helps us to invoke something on main thread
// because 'int c = 1;' probably was expected to be called on
// the caller thread
var cTask = Task.Run(() => return GetC(), syncContext);
cTask.Wait();
int c = cTask.Result;
// This one was with 'await' - calling without syncContext,
// not on the thread, which calls our method.
var dTask = this.GetValueAsync();
dTask.Wait();
int d = dTask.Result;
});
}
Again, this is not the same code which you will get from compiler, but it should just give you some idea how this works. If you really want to take a look on what will be in the produced library, use for example IlSpy to take a look on generated code.
Also I really recommend to read this article Best Practices in Asynchronous Programming
That's exactly what the async keyword means. It takes a method and (usually) converts it to a Task returning method. If the normal method would have the return type of void, the async method will have Task. If the return type would be some other T, the new return type will be Task<T>.
For example, to download an process some data synchronously, you could write something like:
Foo GetFoo()
{
string s = DownloadFoo();
Foo foo = ParseFoo(s);
return foo;
}
The asynchronous version would then look like this:
Task<Foo> GetFoo()
{
string s = await DownloadFoo();
Foo foo = ParseFoo(s);
return foo;
}
Notice that the return type changed from Foo to Task<Foo>, but you're still returning just Foo. And similarly with void-returning methods: since they don't have to contain a return statement, async Task (without any <T>) methods also don't.
The Task object is constructed by the compiler-generated code, so you don't have to do that.