I want to get the thread of a task that is running and not completed. The language I am using is c#, and what I am trying to do is if some action cannot be completed which is locking one of my file, in that case I want to get the thread of that action and destroy the thread and release the file. thats what I want to do.
var task= Task.Run(() => SomeFunction){
getting thread code for the incomplete task here}
Did you mean the Id?
I think you can access it by Task.CurrentId
As stated on this document.
As for completion, you can use Task.IsCompleted.
As states this document.
Related
I'm trying to understand the semantics of async/await in an infinitely looping worker thread started inside a windows service. I'm a newbie at this so give me some leeway here, I'm trying to understand the concept.
The worker thread will loop forever (until the service is stopped) and it processes an external queue resource (in this case a SQL Server Service Broker queue).
The worker thread uses config data which could be changed while the service is running by receiving commands on the main service thread via some kind of IPC. Ideally the worker thread should process those config changes while waiting for the external queue messages to be received. Reading from service broker is inherently asynchronous, you literally issue a "waitfor receive" TSQL statement with a receive timeout.
But I don't quite understand the flow of control I'd need to use to do that.
Let's say I used a concurrentQueue to pass config change messages from the main thread to the worker thread. Then, if I did something like...
void ProcessBrokerMessages() {
foreach (BrokerMessage m in ReadBrokerQueue()) {
ProcessMessage(m);
}
}
// ... inside the worker thread:
while (!serviceStopped) {
foreach (configChange in configChangeConcurrentQueue) {
processConfigChange(configChange);
}
ProcessBrokerMessages();
}
...then the foreach loop to process config changes and the broker processing function need to "take turns" to run. Specifically, the config-change-processing loop won't run while the potentially-long-running broker receive command is running.
My understanding is that simply turning the ProcessBrokerMessages() into an async method doesn't help me in this case (or I don't understand what will happen). To me, with my lack of understanding, the most intuitive interpretation seems to be that when I hit the async call it would go off and do its thing, and execution would continue with a restart of the outer while loop... but that would mean the loop would also execute the ProcessBrokerMessages() function over and over even though it's already running from the invocation in the previous loop, which I don't want.
As far as I know this is not what would happen, though I only "know" that because I've read something along those lines. I don't really understand it.
Arguably the existing flow of control (ie, without the async call) is OK... if config changes affect ProcessBrokerMessages() function (which they can) then the config can't be changed while the function is running anyway. But that seems like it's a point specific to this particular example. I can imagine a case where config changes are changing something else that the thread does, unrelated to the ProcessBrokerMessages() call.
Can someone improve my understanding here? What's the right way to have
a block of code which loops over multiple statements
where one (or some) but not all of those statements are asynchronous
and the async operation should only ever be executing once at a time
but execution should keep looping through the rest of the statements while the single instance of the async operation runs
and the async method should be called again in the loop if the previous invocation has completed
It seems like I could use a BackgroundWorker to run the receive statement, which flips a flag when its job is done, but it also seems weird to me to create a thread specifically for processing the external resource and then, within that thread, create a BackgroundWorker to actually do that job.
You could use a CancelationToken. Most async functions accept one as a parameter, and they cancel the call (the returned Task actually) if the token is signaled. SqlCommand.ExecuteReaderAsync (which you're likely using to issue the WAITFOR RECEIVE is no different. So:
Have a cancellation token passed to the 'execution' thread.
The settings monitor (the one responding to IPC) also has a reference to the token
When a config change occurs, the monitoring makes the config change and then signals the token
the execution thread aborts any pending WAITFOR (or any pending processing in the message processing loop actually, you should use the cancellation token everywhere). any transaction is aborted and rolled back
restart the execution thread, with new cancellation token. It will use the new config
So in this particular case I decided to go with a simpler shared state solution. This is of course a less sound solution in principle, but since there's not a lot of shared state involved, and since the overall application isn't very complicated, it seemed forgivable.
My implementation here is to use locking, but have writes to the config from the service main thread wrapped up in a Task.Run(). The reader doesn't bother with a Task since the reader is already in its own thread.
I have a working thread running all along the runtime, who generates events.
I can handle those events inside the UI thread by using disp = Windows::UI::Core::CoreWindow::GetForCurrentThread()->Dispatcher.
more precisely, I do the modifications to the UI by using disp->RunAsync(...) anywhere inside the working thread.
but I don't know how to do the inverted operation. I want to have some Async function inside the UI thread to perform operation (on some std::unique_ptr) in the working thread when I click on some button.
If I understand correctly you want to be able to run an async operation when a button is clicked, but on a specific thread to which you refer as your worker thread.
First - Since you want to use a resource in 2 threads you should not use unique_ptr and use shared_ptr since you share this resource between the two threads.
Second - if you don't necessarily have to run the action on a specific thread then you can simply use Windows::System::Threading::ThreadPool::RunAsync and capture the shared_ptr by value.
e.g:
namespace WST = Windows::System::Threading;
WST::ThreadPool::RunAsync(
ref new WST::WorkItemHandler(
[mySharedPtr](Windows::Foundation::IAsyncAction^ operation)
{
mySharedPtr->Foo();
}));
In case you have to run the operation on a specific thread then I assume you want to be able to append operations to an already running thread, otherwise you are creating a thread and you can use the above example.
So in order to append operations to an already running thread, that thread must have the functionality of getting a new operations and then running those operations in a synchronous order. This functionality is basically what the Dispatcher provides. This is what an Event Loop is, also called: message dispatcher, message loop, message pump, or run loop. Also you can find information by reading on the Recator\Proactor design pattern.
This CodeProject page shows one way of implementing the pattern, and you can use Winrt component to make it better \ more conveniant \ more familiar
I am using NSURLSession dataTaskWithURL:completionHandler. It looks like completionHandler is executed in a thread which is different than the thread(in my case, it's the main thread) which calls dataTaskWithURL. So my question is, since it is asynchronized, is it possible that the main thread exit, but the completionHandler thread is still running since the response has not come back, which is the case I am trying to avoid. If this could happen, how should I solve the problem? BTW, I am building this as a framework, not an application.Thanks.
In the first part of your question you seem un-sure that the completion handler is running on a different thread. To confirm this let's look at the NSURLSession Class Reference. If we look at the "Creating a Session" section we can see in the description for the following method the answer.
+ sessionWithConfiguration:delegate:delegateQueue:
Swift
init(configuration configuration: NSURLSessionConfiguration,
delegate delegate: NSURLSessionDelegate?,
delegateQueue queue: NSOperationQueue?)
Objective-C
+ (NSURLSession *)sessionWithConfiguration:(NSURLSessionConfiguration *)configuration
delegate:(id<NSURLSessionDelegate>)delegate
delegateQueue:(NSOperationQueue *)queue
In the parameters table for the NSOperationQueue queue parameter is the following quote.
An operation queue for scheduling the delegate calls and completion handlers. The queue need not be a serial queue. If nil, the session creates a serial operation queue for performing all delegate method calls and completion handler calls.
So we can see the default behavior is to provide a queue whether from the developer or as the default class behavior. Again we can see this in the comments for the method + sessionWithConfiguration:
Discussion
Calling this method is equivalent to calling
sessionWithConfiguration:delegate:delegateQueue: with a nil delegate
and queue.
If you would like a more information you should read Apple's Concurrency Programming Guide. This is also useful in understanding Apple's approach to threading in general.
So the completion handler from - dataTaskWithURL:completionHandler: is running on a different queue, with queues normally providing their own thread(s). This leads the main component of your question. Can the main thread exit, while the completion handler is still running?
The concise answer is no, but why?
To answer this answer this we again turn to Apple's documentation, to a document that everyone should read early in their app developer career!
The App Programming Guide
The Main Run Loop
An app’s main run loop processes all user-related events. The
UIApplication object sets up the main run loop at launch time and uses
it to process events and handle updates to view-based interfaces. As
the name suggests, the main run loop executes on the app’s main
thread. This behavior ensures that user-related events are processed
serially in the order in which they were received.
All of the user interact happens on the main thread - no main thread, no main run loop, no app! So the possible condition you question mentions should never exist!
Apple seems more concerned with you doing background work on the main thread. Checkout the section "Move Work off the Main Thread"...
Be sure to limit the type of work you do on the main thread of your
app. The main thread is where your app handles touch events and other
user input. To ensure that your app is always responsive to the user,
you should never use the main thread to perform long-running or
potentially unbounded tasks, such as tasks that access the network.
Instead, you should always move those tasks onto background threads.
The preferred way to do so is to use Grand Central Dispatch (GCD) or
NSOperation objects to perform tasks asynchronously.
I know this answer is long winded, but I felt the need to offer insight and detail in answering your question - "the why" is just as important and it was good review :)
NSURLSessionTasks always run in background by default that's why we have completion handler which can be used when we get response from Web service.
If you don't get any response explore your request URL and whether HTTPHeaderFields are set properly.
Paste your code so that we can help it
I just asked the same question. Then figured out the answer. The thread of the completion handler is setup in the init of the NSURLSession.
From the documentation:
init(configuration configuration: NSURLSessionConfiguration,
delegate delegate: NSURLSessionDelegate?,
delegateQueue queue: NSOperationQueue?)`
queue - A queue for scheduling the delegate calls and completion handlers. If nil, the session creates a serial operation queue for performing all delegate method calls and completion handler calls.*
My code that sets up for completion on main thread:
var session = NSURLSession(configuration: configuration, delegate:nil, delegateQueue:NSOperationQueue.mainQueue())
(Shown in Swift, Objective-C the same) Maybe post more code if this does not solve.
I am having a task like below.
var task = Task<string>.Factory.StartNew(() => longrunningmethod()
.ContinueWith(a =>
longrunningmethodcompleted((Task<string>)a,
TaskScheduler.FromCurrentSynchronizationContext())));
task.Wait();
My task will call the longrunningmethod and after completing it will call completed method.
Inside my longrunningmethod I am delaying by Thread.Sleep(30000). When I use Task.wait system hangs and it's not calling longrunningmethodcompleted method. If I don't use Task.wait everything flows good.
I strongly suspect your context is a UI context.
In that case, you're causing the deadlock because you're telling longrunningmethodcompleted to execute on the current SynchronizationContext.
Then you're blocking that context by calling Wait. The continuation will never complete because it needs to execute on the thread that is blocked in Wait.
To fix this, you can't use Wait on a continuation running in that context. I'm assuming that longrunningmethodcompleted must run on the UI thread, so the solution is to replace the call to Wait with a call to ContinueWith:
var ui = TaskScheduler.FromCurrentSynchronizationContext();
var task = Task<string>.Factory.StartNew(() => longrunningmethod()
.ContinueWith(a =>
longrunningmethodcompleted((Task<string>)a,
ui);
task.ContinueWith(..., ui);
Or, you can upgrade to VS2012 and use async/await, which lets you write much cleaner code like this:
var task = Task.Run(() => longrunningmethod());
await task;
longrunningmethodcompleted(task);
Well it is hard to tell what is wrong with your code without seeing what the actual asynch actions are, all I know is according to MSDN waits for the task to be completed. Is it possible that because you are trying to use the current SynchronizationContext your actions blocks?
The reason I am asking is because you
Start the taskWait for the task to complete (which is the continue with task)Task tries to continue with current SynchronizationContextTask tries to acquire the main threadTask scheduled to take the thread after the Wait is completedBut Wait is waiting on current Task to complete (deadlock)
What I mean is that the reason your program works with Thread.Sleep(seconds) is because after the time limit is up the thread will continue.
Thread.Sleep(nnn) is blocking. Use Task.Delay(nnn) and await:
await Task.Delay(30000);
Edited to add: Just noted the tag says C# 4. This requires C# 5 and the new async await support. Seriously, if you're doing async and tasks, you need to upgrade.
I don't understand the explanation in offical document:
Logical threads can jump from one managed thread to another.
What's the different between ThreadContext and ThreadLogicalContext?
Can someone elaborate on it?
Thanks.
I should go back and add this to my own question (that Stefan Egli linked above) ...
From what I can tell, there is very little practical difference between the two.
ThreadContext stores information in a Dictionary that is stored using Thread.SetData.
ThreadLogicalContext stores its information in a Dictionary that is stored using the CallContext.
Information stored in the CallContext has almost the same
accessibility as information stored using Thread.SetData. That is, the information is accessibli to the thread that stored the information in the first place.
Now, IF the ThreadLogicalContext used CallContext.LogicalSetData (or if the Dictionary stored using CallContext.SetData implemented the marker interface, IThreadAffinative) then there WOULD be BIG difference. In that case, any information stored (LogicalSetData) could be accessed within the same thread AND is passed to child threads. In addition (flows with the logical thread), the
information can flow across remoting calls and across AppDomains (if the data is Serializable).
I would have put in some links, but am working from iPhone so is a little awkward. There are some good links in the link that Stefan Egli posted above.
Also, look at Jeffrey Richter's blog from September for an article on CallContext.LogicalSetData. I used his test program as a basis for comparing CallContext.SetData vs CallContext.LogicalSetData vs Thread.SetData vs [ThreadStatic]. Last time I checked, it was the last
thing he posted.
Will try to come back and post more links and/or some sample code when I have easy access to computer.
Good luck!
From using this myself, I see the benefit of using the ThreadLogicalContext when working with multi threaded logic (async, await).
For example, if you set the property on your original calling thread using ThreadContext, it is also available to any other tasks that get to run on the same thread.
// caller thread (thread #1)
log4net.ThreadContext.Properties["MyProp"] = "123"; // now set on thread #1
log("start");
await Task.WhenAll(
MyAsync(1), // `Issue` if task run on thread #1, it will have "MyProp"
MyAsync(2) // `Issue` if task run on thread #1, it will have "MyProp"
);
log("end"); // `Issue` only by random chance will you run on thread #1 again
Where as if you use ThreadLogicalContext, it stays on the calling context.
// caller thread (thread #1)
log4net.LogicalThreadContext.Properties["MyProp"] = "123"; // now set on calling context
log("start");
await Task.WhenAll(
MyAsync(1), // if task run on thread #1, there is no "MyProp"
MyAsync(2) // if task run on thread #1, there is no "MyProp"
);
log("end"); // if task run on thread #1, there is no "MyProp"
With await you are never guaranteed you come back to the same thread as when you started and the calling context will have changed, so you will have to set the property again.
...
log4net.LogicalThreadContext.Properties["MyProp"] = "123";
log("end");