Form1.cs public PrinterProcess CurrentPrinter; private async void btnPrinter_Click(object sender, EventArgs e) { try { CurrentPrinter = new PrinterProcess(); var result = await Task.Run(() => CurrentPrinter.DoProcess()); } catch (System.OperationCanceledException ex) { Trace.WriteLine("Cancelled"); } Trace.WriteLine("Done"); } private void btnIN_Click(object sender, EventArgs e) { CurrentPrinter.CurrentState = Core.STATE.In; } private void btnSTART_Click(object sender, EventArgs e) { CurrentPrinter.CurrentState = Core.STATE.START; } private void btnOUT_Click(object sender, EventArgs e) { CurrentPrinter.CurrentState = Core.STATE.OUT; } private void btnCancel_Click(object sender, EventArgs e) { //CurrentPrinter.CurrentState = Core.STATE.CANCEL; if (CurrentPrinter.MyCancellationTokenSource != null) CurrentPrinter.MyCancellationTokenSource.Cancel(); } // ###################### public enum STATE { NotDefine = -1, In = 0, START = 1, OUT = 2, CANCEL = 3 } public class ServerData { public int Index { set; get; } public string Code { set; get; } public string BestBefore { set; get; } public bool IsFreeForMarking { set; get; } public override string ToString() { return $"Index={Index}, Code={Code}, Bestbefore={BestBefore}, IsFreeForMarking={IsFreeForMarking}"; //return base.ToString(); } } public class ServerDataList : List { } public class PrinterProcess { public STATE CurrentState; public ServerDataList ServerData; public List ListPossibleToMark; public CancellationTokenSource MyCancellationTokenSource; public PrinterProcess() { CurrentState = STATE.NotDefine; MyCancellationTokenSource = new CancellationTokenSource(); } Task DoIn(CancellationToken token, string text) { return Task.Run(() => { for (var i = 0; i < 10; ++i) { Trace.WriteLine($"{text} loop DataFromServer Code= '{i,22:D22}'"); ServerData.Add(new ServerData() { BestBefore = "12/2023", Code = $"{i,22:D22}", Index = i }); if (token.IsCancellationRequested) { token.ThrowIfCancellationRequested(); return $"{text} cancelled"; } try { // Make work Thread.Sleep(600); } catch (OperationCanceledException) { Trace.WriteLine("DoIn The wait operation was canceled."); // not calling, however! throw; } } return $"{text} Done"; }); } Task DoInCamera(CancellationToken token, string text) { return Task.Run(() => { for (var i = 0; i < 10; ++i) { Trace.WriteLine($"{text} loop check with camera, free for marking pos= '{i,4:D4}'"); //var qry = ServerData.Where(y => y.Index == i).FirstOrDefault(); ListPossibleToMark.Add(i % 2 == 0); //qry.IsFreeForMarking = true; if (token.IsCancellationRequested) { token.ThrowIfCancellationRequested(); //return $"{text} cancelled"; } try { // Make work Thread.Sleep(1600); } catch (OperationCanceledException) { Trace.WriteLine("DoInCamera The wait operation was canceled."); // not calling, however! throw; } } // return $"{text} Done"; }); } Task DoStart(CancellationToken token, string text) { return Task.Run(() => { foreach (var item in ServerData) { if (ListPossibleToMark[item.Index]) Trace.WriteLine($"{text} loop PrintTheData {item.ToString()} mark possible"); else Trace.WriteLine($"{text} loop PrintTheData {item.ToString()} not possible"); if (token.IsCancellationRequested) { token.ThrowIfCancellationRequested(); return $"{text} cancelled"; } Thread.Sleep(500); } return $"{text} Done"; }); } public async Task DoProcess() { var token = MyCancellationTokenSource.Token; Task taskIn = null; Task taskInCamera = null; Task taskStart = null; Task taskOut = null; int orderAmountMustBe = 1000; int orderAmountCurrent = 0; try { while (true) { ++orderAmountCurrent; if (orderAmountCurrent >= orderAmountMustBe) break; switch (CurrentState) { default: break; case STATE.In: ServerData = new ServerDataList(); ListPossibleToMark = new List(); MyCancellationTokenSource = new CancellationTokenSource(); // every time new, in case of cancel, can't be done again, we need a new instance. token = MyCancellationTokenSource.Token; //source = new CancellationTokenSource(); //if (token.Status == TaskStatus.Canceled) taskIn = DoIn(token, "DoIn taskIn"); taskInCamera = DoInCamera(token, "DoIn taskInCamera"); CurrentState = STATE.NotDefine; break; case STATE.START: // string[] startResult = await Task.WhenAll(taskIn, taskInCamera); // not possible, different return values await Task.WhenAll(taskIn, taskInCamera); if (taskIn != null && taskInCamera != null) { var serverData = await taskIn; await taskInCamera; // void (Task) no return value taskStart = DoStart(token, "DoStart taskStart"); } CurrentState = STATE.NotDefine; break; case STATE.OUT: string[] outResult = await Task.WhenAll(taskIn, taskStart); foreach (var item in outResult) { Trace.WriteLine($"Task -> {item} ready! Product can move to next machine"); } CurrentState = STATE.NotDefine; break; case STATE.CANCEL: // not working!!! Because I'm waitung in the START state, when not possible! //MyCancellationTokenSource.Cancel(); //Trace.WriteLine($"Cancel State machine"); //CurrentState = STATE.NotDefine; break; } Thread.Sleep(10); } //await Task.WhenAll(taskIn, taskStart, taskOut); } catch (Exception ex) { Trace.WriteLine($"Exception = {ex.Message}\n{ex.StackTrace}"); return ex.Message; } //catch (OperationCanceledException) not working //{ // Interlock.Exchange(ref process, 0); // Trace.WriteLine("The wait operation was canceled."); // throw; //} //finally //{ //} return "Ready Order"; //return $"{taskIn.Result}, {taskStart.Result}, {taskOut.Result}"; } }