I have started a task on Start Task button click and want to cancel that task > using Cancel Task button. But I am not able to find & cancel running task.
public ActionResult StartTask()
{
var tokenSource = new CancellationTokenSource();
CancellationToken ct = tokenSource.Token;
Task.Factory.StartNew(() =>
{
// do some work...
}, tokenSource.Token);
return view();
}
public ActionResult CancelTask()
{
//Here i want to cancel above task.
return view();
}
Thanks in advance...
Please try passing the CancellationToken as the second parameter to Task.Factory.StartNew
CancellationToken ct = tokenSource.Token;
Task.Factory.StartNew(() =>
{
// do some work...
if (ct.IsCancellationRequested)
{
// another thread decided to cancel
Console.WriteLine("task canceled");
break;
}
}, ct);
and issue tokenSource.Cancel() to cancel
Note: A similar thread can be found here
How do I abort/cancel TPL Tasks?
Related
I've created a simple news bot which sends updates to a user every 24 hours. I've created a callback controller which handles requests from an external service, processes the resumptionCookie, then sends a carousel of articles with two buttons to the user. One of the buttons opens a browser window, the other should trigger a new dialog (OptionsDialog).
Is this implementation correct? and is it possible to suspend any active dialog, whilst the user interacts with the news article message? For example, if i'm going through a particular dialog, then suddenly I get a news alert, is it possible to suspend the current dialog, to allow the user to update the options of the alerts (almost like the news alert is outside the normal dialog flow), then once they've finished they'll return to the previous dialog. Hopefully, the question is clear enough. Any help will be greatly appreciated.
public class CallbackController : ApiController
{
public async Task<IHttpActionResult> Post(ResumptionCookie resumptionCookie)
{
var activity = (Activity)resumptionCookie.GetMessage();
var reply = activity.CreateReply();
reply.Text = "We found 7 news articles that match your criteria";
reply.Attachments = new List<Attachment>
{
new ThumbnailCard
{
Buttons = new List<CardAction>
{
new CardAction(ActionTypes.OpenUrl, "BBC", null, "http://www.bbc.co.uk"),
new CardAction(ActionTypes.PostBack, "Update Options", null, "Update Options")
}
}.ToAttachment()
};
var client = new ConnectorClient(new Uri(activity.ServiceUrl));
await client.Conversations.ReplyToActivityAsync(reply);
return Ok(new { success = true });
}
}
This is my Main dialog
[Serializable]
public class MainDialog : IDialog
{
public async Task StartAsync(IDialogContext context)
{
context.Wait(ProcessMessage);
}
private async Task ProcessMessage(IDialogContext context, IAwaitable<IMessageActivity> result)
{
var response = await result;
if (response.Text.Equals("Update Options", StringComparison.OrdinalIgnoreCase))
{
context.Call(new OptionsDialog(), FinishMainDialog);
}
else
{
PromptDialog.Confirm(context, ProcessChoice, "Do you wish to continue?");
}
}
private async Task ProcessChoice(IDialogContext context, IAwaitable<bool> result)
{
var choice = await result;
if(choice)
{
context.Call(new DialogOne(), FinishMainDialog);
}
else
{
context.Done(true);
}
}
private async Task FinishMainDialog(IDialogContext context, IAwaitable<object> result)
{
context.Done(true);
}
}
Here is my frequency dialog
[Serializable]
public class OptionsDialog : IDialog
{
public async Task StartAsync(IDialogContext context)
{
await context.PostAsync("You can update your to options here");
context.Wait(ProcessMessage);
}
public async Task ProcessMessage(IDialogContext context, IAwaitable<IMessageActivity> activity)
{
await context.PostAsync("Hello, World!");
context.Done(true);
}
}
Im trying to implement windows phone 8.1 notification background task.
it is implemented with one bug!
the toast notification message will appear in the action center more than once. sometimes 9times.
here is my code:
public sealed class my_bg_notifier: IBackgroundTask
{
public async void Run(IBackgroundTaskInstance taskInstance)
{
var deferral = taskInstance.GetDeferral();
bool status = await notificationChecker.check();
if (status)
{
populateNotification(notificationChecker.count);
}
deferral.Complete();
}
}
I tried to debug so I put a breakpoint over the line status.
and I was surprised that it is called more than once and that is why my notification will pop-up more than one time.
and the message that is showed from the debugger breakpoint clearly states that there are multiple threads doing the same job simultaneously.
so i thought to prevent running the method by more than one thread by using a boolean flag as follow:
public sealed class my_bg_notifier: IBackgroundTask
{
private static bool isNotBusy = true;
public async void Run(IBackgroundTaskInstance taskInstance)
{
if (isNotBusy)
{
isNotBusy = false;
var deferral = taskInstance.GetDeferral();
bool status = await notificationChecker.check();
if (status)
{
populateNotification(notificationChecker.count);
}
deferral.Complete();
}
isNotBusy = true;
}
}
but again that didn't work.
my question is :
why would a background task run more than once by multiple thread simultanously.
and How can I block this behavioud? should I use lock keyword?
Okkkkk!!! It was my fault. In my code i registered the background task on each app launch without checking if it is already registered.
So i used code as below to check if my task is registered then no need to register it again.
var taskRegistered = false;
var exampleTaskName = "ExampleBackgroundTask";
foreach (var task in Background.BackgroundTaskRegistration.AllTasks)
{
if (task.Value.Name == exampleTaskName)
{
taskRegistered = true;
break;
}
}
Source: http://msdn.microsoft.com/en-us/library/windows/apps/xaml/hh977055.aspx
I have a server listening for requests using HttpListener.Listen() with support for cancellation using CancellationTokenSource.Token. This is on c# 4.0.
The calling code:
Task.Factory.StartNew(() =>
{
myServer = new MyServer();
myServer.Listen(new[] { "http://*:8085/" }, cancel.Token);
});
MyServer:
public void Listen(IEnumerable<string> prefixes, CancellationToken cancel)
{
httpListener = new HttpListener();
foreach(var p in prefixes) httpListener.Prefixes.Add(p);
httpListener.Start();
// watch for cancellation
while(!cancel.IsCancellationRequested)
{
var result = httpListener.BeginGetContext(callback =>
{
var listener = (HttpListener)callback.AsyncState;
if(!listener.IsListening) return;
var httpContext = listener.EndGetContext(callback);
// handle the request in httpContext, some requests can take some time to complete
}, httpListener);
while(result.IsCompleted == false)
{
if(cancel.IsCancellationRequested) break;
Thread.Sleep(100); // sleep and recheck
}
}
httpListener.Stop();
}
So far it seems to work fine, but it seems like an overly long piece of code.
I tried to use FromAsync() as such:
public void Listen(IEnumerable<string> prefixes, CancellationToken cancel)
{
httpListener = new HttpListener();
foreach(var p in prefixes) httpListener.Prefixes.Add(p);
httpListener.Start();
while(!cancel.IsCancellationRequested)
{
Task.Factory.FromAsync<HttpListenerContext>(httpListener.BeginGetContext, httpListener.EndGetContext, null).ContinueWith(t =>
{
var httpContext = t.Result;
// do stuff
}, cancel);
}
httpListener.Stop();
}
but what happens is i will run out of memory very quickly because many Tasks are created inside the while loop.
Any suggestions on how to resolve this problem? or how to clean up my first attempt?
I saw some answers on some other threads but those use .net 5.0 while my project is on .net 4.0.
I want to perform some long running operation (e.g. listening to some event raised by OS) on the background thread. Most of the times, operation will run continuously without any problem. But in certain rare conditions, OS level API sends some error code and I need to raise exception from background thread which has to be propagated to the main thread to show it to the user of my WinFrom application.
I had decided to use BackgroundWorker for this. But .NET 4.0 provides Task class of the Task Parallel Library which is a better option as per various blogs on the TPL.
In my application, I have to kick off the background task before actual form is shown. Since actual code is quite complex, I have written some sample code simulating real time problem:
public static Task task;
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
ThreadTest tt = new ThreadTest();
task = new Task(() => tt.PerformTask("hi"));
task.Start();
try
{
task.Wait();
}
catch (AggregateException aggregateException)
{
// Handle exception here.
}
Application.Run(new Form1());
}
In this code, I never see the main form simply because background task keeps running without exception and task.Wait() call makes the current thread waiting until background task finishes!
Can I use TPL's Task for such scenarios where main thread should not wait until background task is finished but at the same time, it should get exception details whenever exception is raised from the background task?
In above code, one of the solutions could be to move the task creation code at some later stage. But my question is more academic in this case.
Yes you can. Please see the code below.
The program code is:
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
CancellationTokenSource cancellationTokenSource = new CancellationTokenSource();
Task longRunningTask = new Task((state) =>
{
LongRunningWork.DoWork( cancellationTokenSource.Token);
},cancellationTokenSource.Token,TaskCreationOptions.LongRunning);
var newForm = new Form1(cancellationTokenSource);
new Thread((state) =>
{
longRunningTask.Start();
try
{
longRunningTask.Wait();
}
catch (AggregateException exception)
{
Action<Exception> showError = (ex) => MessageBox.Show(state as Form, ex.Message);
var mainForm = state as Form;
if (mainForm != null)
{
mainForm.BeginInvoke(showError, exception.InnerException);
}
}
}).Start(newForm);
Application.Run(newForm);
And the code for the long running task is:
public class LongRunningWork
{
public static void DoWork( CancellationToken cancellationToken)
{
int iterationCount = 0;
//While the
while (!cancellationToken.IsCancellationRequested &&iterationCount <5)
{
//Mimic that we do some long jobs here
Thread.Sleep(1000);
iterationCount++;
//The jobs may throw the exception on the specific condition
if (iterationCount ==5)
{
throw new InvalidOperationException("Invalid action");
}
}
//cancel the task
cancellationToken.ThrowIfCancellationRequested();
}
}
Finally, the code for the Form1 which includes a exit button, whose function is to terminate the program on clicking.
public partial class Form1 : Form
{
private CancellationTokenSource _cancellationTokenSource;
public Form1()
{
InitializeComponent();
}
public Form1(CancellationTokenSource cancellationTokenSource):this()
{
_cancellationTokenSource = cancellationTokenSource;
}
private void exitBtn_Click(object sender, EventArgs e)
{
//Cancel out the task
if (_cancellationTokenSource != null)
{
_cancellationTokenSource.Cancel();
}
//Exit the program
Application.Exit();
}
}
Start your long running operation from the form itself rather than before the form is created. Remember that Application.Run() starts a message loop on the current thread, but that means you can use that message loop to poll your task from the Timer class.
class Form1 : Form
{
private Timer PollingTimer;
private Task BackgroundTask;
public Form1()
{
InitializeComponent();
// Begin the background task.
ThreadTest tt = new ThreadTest();
this.BackgroundTask = new Task(() => tt.PerformTask("hi"));
this.BackgroundTask.Start();
// Monitor the task's status by polling it regularly.
this.PollingTimer = new Timer();
this.PollingTimer.Interval = 1000; // In milliseconds.
this.PollingTimer.Tick += timerCallback;
this.PollingTimer.Start();
}
private timerCallback(object sender, EventArgs e)
{
if (this.BackgroundTask.IsFaulted)
{
// Exception information is in BackgroundTask.Exception.
}
}
}
If you dislike polling (which I do), you'll need to catch the exception from your task and marshall it back to your UI thread. The best way to do that is simply not catch the exception in the task itself and provide a continuation method which will only execute on error.
class Form1 : Form
{
private Task BackgroundTask;
public Form1()
{
InitializeComponent();
// Capture the UI thread context.
// (Note, it may be safer to run this in the Form.Load event than the constructor.
var uiContext = TaskScheduler.FromCurrentSynchronizationContext();
// Begin the background task.
ThreadTest tt = new ThreadTest();
this.BackgroundTask = new Task(() => tt.PerformTask("hi"))
// Schedule a continuation to be executed after the task is completed.
.ContinueWith((t,arg) =>
{
// Exception information is in t.Exception
},null, null,
// Only execute the continuation if the task throws an exception.
TaskContinuationOptions.OnlyOnFaulted,
// Execute the continuation on the UI thread we captured above.
uiContext);
this.BackgroundTask.Start();
}
}
MSDN references for Task.ContinueWith() and TaskScheduler.FromCurrentSynchronizationContext().
And, if you have the luxury of .NET 4.5 with async and await:
class Form1 : Form
{
private Task BackgroundTask;
public Form1()
{
InitializeComponent();
}
private async void Form1_Load(object sender, EventArgs e)
{
ThreadTest tt = new ThreadTest();
try
{
// Move your Task creation and start logic into a method.
await tt.RunAsync();
}
catch (Exception ex)
{
// Really smart compiler writers make sure you're on the right thread
// and everything Just Works(tm).
}
}
}
Part of my Silverlight application requires data from three service requests. Up until now I've been chaining the requests so as one completes the other starts... until the end of the chain where I do what I need to do with the data.
Now, I know thats not the best method(!). I've been looking at AutoResetEvent (link to MSDN example) to thread and then synchronize the results but cannot seem to get this to work with async service calls.
Does anyone have any reason to doubt this method or should this work? Code samples gratefully received!
Take a look at this example:
Will fire Completed event and print 'done' to Debug Output once both services returned.
Key thing is that waiting for AutoResetEvents happens in background thread.
public partial class MainPage : UserControl
{
public MainPage()
{
InitializeComponent();
Completed += (s, a) => { Debug.WriteLine("done"); };
wrk.DoWork += (s, a) =>
{
Start();
};
wrk.RunWorkerAsync();
}
public event EventHandler Completed;
private void Start()
{
auto1.WaitOne();
auto2.WaitOne();
Completed(this, EventArgs.Empty);
}
public AutoResetEvent auto1 = new AutoResetEvent(false);
public AutoResetEvent auto2 = new AutoResetEvent(false);
BackgroundWorker wrk = new BackgroundWorker();
private void Button_Click(object sender, RoutedEventArgs e)
{
ServiceReference1.Service1Client clien = new SilverlightAsyncTest.ServiceReference1.Service1Client();
clien.DoWorkCompleted += new EventHandler<SilverlightAsyncTest.ServiceReference1.DoWorkCompletedEventArgs>(clien_DoWorkCompleted);
clien.DoWork2Completed += new EventHandler<SilverlightAsyncTest.ServiceReference1.DoWork2CompletedEventArgs>(clien_DoWork2Completed);
clien.DoWorkAsync();
clien.DoWork2Async();
}
void clien_DoWork2Completed(object sender, SilverlightAsyncTest.ServiceReference1.DoWork2CompletedEventArgs e)
{
Debug.WriteLine("2");
auto1.Set();
}
void clien_DoWorkCompleted(object sender, SilverlightAsyncTest.ServiceReference1.DoWorkCompletedEventArgs e)
{
Debug.WriteLine("1");
auto2.Set();
}
}
It could be done using the WaitHandle in the IAsyncResult returned by each async method.
The code is simple. In Silverlight I just do 10 service calls that will add an item to a ListBox. I'll wait until all the service calls end to add another message to the list (this has to run in a different thread to avoid blocking the UI). Also note that adding items to the list have to be done through the Dispatcher since they will modify the UI. There're a bunch of lamdas, but it's easy to follow.
public MainPage()
{
InitializeComponent();
var results = new ObservableCollection<string>();
var asyncResults = new List<IAsyncResult>();
resultsList.ItemsSource = results;
var service = new Service1Client() as Service1;
1.To(10).Do(i=>
asyncResults.Add(service.BeginDoWork(ar =>
Dispatcher.BeginInvoke(() => results.Add(String.Format("Call {0} finished: {1}", i, service.EndDoWork(ar)))),
null))
);
new Thread(()=>
{
asyncResults.ForEach(a => a.AsyncWaitHandle.WaitOne());
Dispatcher.BeginInvoke(() => results.Add("Everything finished"));
}).Start();
}
Just to help with the testing, this is the service
public class Service1
{
private const int maxMilliSecs = 500;
private const int minMillisSecs = 100;
[OperationContract]
public int DoWork()
{
int millisSecsToWait = new Random().Next(maxMilliSecs - minMillisSecs) + minMillisSecs;
Thread.Sleep(millisSecsToWait);
return millisSecsToWait;
}
}