Tasks, main task, sub task

Markus Freitag 3,791 Reputation points
2023-06-16T16:17:40.9566667+00:00

Hello,

How are they handled and terminated correctly. Sample examples would be good. I trigger a Cancel and all tasks should exit cleanly. How do I achieve this? The problem is, there are so many options, but few good ones. You have to know them. I want to do it right. It only works if I know the possibilities.

Picture:

1__Process_IO_Errorhandling_NIO

Picture States

enter image description here

Process -> Task/Thread
ServerData -> Task/Thread Print -> Task/Thread

I am a bit in the dark, could someone let me know how I would need to create the architecture correctly. With sample code.

Can I give a TaskName, like Process ServerData Print If I press CANCEL, then check the Thread, task name.

I have states, IN; START; OUT These are activated and set externally. Depending on the state, it may be that tasks have not yet been processed, although the next state is already set.

Background, a part is moved mechanically and set the event. I simulate it with bottons. Something is wrong, what, I don't know. Can you give me tips please?

Code:

private void btnIN_Click(object sender, EventArgs e)
{
	MyServiceObject.CurrentState = STATE.In;
}

private void btnSTART_Click(object sender, EventArgs e)
{
	MyServiceObject.CurrentState = STATE.START;
}

private void btnOUT_Click(object sender, EventArgs e)
{
	MyServiceObject.CurrentState = STATE.OUT;
}

private void Form1_Load(object sender, EventArgs e)
{

}

// ************************************************
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 class ServerDataList : List<ServerData>
{
	public bool DataReady { set; get; }


	public Task GetServerDataVariant2(CancellationToken ct, ConcurrentBag<Task> cb)
	{
		Task t;
	   
		t = Task.Run(() =>
		{
			//cb.Add(t);
			if (ct.IsCancellationRequested)
			{
				Trace.WriteLine($"GetServerDataAsync Task id= '{Thread.CurrentThread.ManagedThreadId}' was cancelled before it got started.");

				ct.ThrowIfCancellationRequested();
			}

			var list = new List<ServerData>();
			//for (int i = 0; i < 300000; i++)
			for (int i = 0; i < 200; i++)
			{
				Add(new ServerData()
				{
					BestBefore = "12/2023",
					Code = $"{i,22:D22}",
					Index = i
				});
				Trace.WriteLine($"Code= '{this[Count - 1].Code}',   ThreadID= '{Thread.CurrentThread.ManagedThreadId}'");
				Thread.Sleep(2);


				if (ct.IsCancellationRequested)
				{
					Trace.WriteLine($"GetServerDataVariant2 Task '{Thread.CurrentThread.ManagedThreadId}' cancelled");
					// Trace.WriteLine($"GetServerDataVariant2 Task '{t.Id}' cancelled");
					//ct.ThrowIfCancellationRequested();
					break;
				}
			}
			// return t; // list;
		});
		cb.Add(t);
		return t;
	}


	public Task<List<ServerData>> GetServerDataAsync(CancellationToken ct, ConcurrentBag<Task> cb)
	{
		// var serverData = await GetServerDataAsync();
		// I can't wait, because the product is moving meanwhile the request of the server data.
		// Was cancellation already requested?         
		return Task.Run(() =>
			{
				if (ct.IsCancellationRequested)
				{
					Trace.WriteLine($"GetServerDataAsync Task id= '{Thread.CurrentThread.ManagedThreadId}' was cancelled before it got started.");
					ct.ThrowIfCancellationRequested();
				}

				var list = new List<ServerData>();
				//for (int i = 0; i < 300000; i++)
				for (int i = 0; i < 200; i++)
				{
					Add(new ServerData()
					{
						BestBefore = "12/2023",
						Code = $"{i,22:D22}",
						Index = i
					});
					Trace.WriteLine($"Code= '{this[Count - 1].Code}',   ThreadID= '{Thread.CurrentThread.ManagedThreadId}'");
					Thread.Sleep(2);


					if (ct.IsCancellationRequested)
					{
						Trace.WriteLine($"GetServerDataAsync Task '{Thread.CurrentThread.ManagedThreadId}' cancelled");
						ct.ThrowIfCancellationRequested();
					}
				}
				return list;
			});
	}

	public void GetServerData(CancellationToken ct)
	{
		//https://learn.microsoft.com/de-de/dotnet/standard/parallel-programming/how-to-cancel-a-task-and-its-children
		// Was cancellation already requested?
		if (ct.IsCancellationRequested)
		{
			Trace.WriteLine($"Task id= '{Thread.CurrentThread.ManagedThreadId}' was cancelled before it got started.");
			ct.ThrowIfCancellationRequested();
		}
		DataReady = false;
		//for (int i = 0; i < 300000; i++)
		for (int i = 0; i < 200; i++)
		{
			Add(new ServerData()
			{
				BestBefore = "12/2023",
				Code = $"{i,22:D22}",
				Index = i
			});
			Trace.WriteLine($"Code= '{this[Count - 1].Code}',   ThreadID= '{Thread.CurrentThread.ManagedThreadId}'");
			Thread.Sleep(2);

			if (ct.IsCancellationRequested)
			{
				Trace.WriteLine($"Task '{Thread.CurrentThread.ManagedThreadId}' cancelled");
				ct.ThrowIfCancellationRequested();
			}
		}
		DataReady = true;
	}

	public bool IsDataFromServerReady(CancellationToken ct)
	{
		while (!DataReady)
		{
			Thread.Sleep(50);
		}
		return DataReady;
	}

	public bool IsProductResult(int amount)
	{
		if (amount > 30)
			return true;
		return false;
	}
}

public class MyService
{
	ServerDataList MyServerData = new ServerDataList();


	ConcurrentBag<Task> CB;

	public CancellationTokenSource TokenSource = new CancellationTokenSource();
	public CancellationToken Ct;

	private ManualResetEvent ManualResetEvent = new ManualResetEvent(false);
	private Stopwatch SW = new Stopwatch();

	public STATE CurrentState = STATE.NotDefine;

	public int EventNo { set; get; } = 0;

	public MyService()
	{
		Ct = TokenSource.Token;
		CB = new ConcurrentBag<Task>();
	}

	public async Task<int> Process()
	{
		try
		{

			while (true)
			{
				switch (CurrentState)
				{
					default:
						break;
					case STATE.In:
						CurrentState = STATE.NotDefine;

						ManualResetEvent.Reset();
						Trace.WriteLine($"Work {CurrentState},   ThreadID= '{Thread.CurrentThread.ManagedThreadId}' seconds= '{SW.Elapsed.Seconds}'");
						EventIn();

						break;
					case STATE.START:
						CurrentState = STATE.NotDefine;

						EventStart();
						break;
					case STATE.OUT:


						CurrentState = STATE.NotDefine;
						break;
					case STATE.CANCEL:
						TokenSource.Cancel();
						ManualResetEvent.Set();
						Trace.WriteLine($"Work {CurrentState},   ThreadID= '{Thread.CurrentThread.ManagedThreadId}'");
						break;
				}

				if (CurrentState == STATE.CANCEL)
					break;

				await Task.Delay(10);
			}


		}
		catch (OperationCanceledException ex)
		{
			Trace.WriteLine($"\n{nameof(OperationCanceledException)} thrown\n{ex.Message}\n{ex.StackTrace}");
		}
		finally
		{
			//   if (ManualResetEvent.WaitOne(2000))
			//      TokenSource.Dispose();

			await Task.WhenAll(CB.ToArray());
		}
		return 0;
	}

	public async void EventIn()
	{
		//try
		//{
		ManualResetEvent.Reset();
		//Task.Run(() => MyServerData.GetServerData(Ct));

		//Task<List<ServerData>> serverData = await MyServerData.GetServerDataAsync();
		//var serverData = await MyServerData.GetServerDataAsync(Ct, CB);

		await MyServerData.GetServerDataVariant2(Ct, CB);

		ManualResetEvent.Set();

		//}
		//catch (OperationCanceledException)
		//{
		//    Console.WriteLine($"\n{nameof(OperationCanceledException)} thrown\n");
		//}
		//finally
		//{
		//    //TokenSource.Dispose();
		//}
		//MessageBox.Show("EventIn");
	}

	public void EventStart()
	{
		//ServerDataList MyServerDataSub = new ServerDataList();
		//await Task.Run(() => MyServerData.IsDataFromServerReady(Ct));
		//MessageBox.Show("EventStart");

		if (!ManualResetEvent.WaitOne(5000))
		{
			TokenSource.Cancel();
			//MessageBox.Show("TimeOut EventStart", "Info....", MessageBoxButtons.OK, MessageBoxIcon.Error);
			Trace.WriteLine($"EventStart TokenSource.Cancel() Timeout ####  ");
		}
		else
		{
			Trace.WriteLine($"EventStart All fine, product can be produced ####  ");

			foreach (var item in MyServerData)
			{
				Trace.WriteLine($"Produce   Index= '{item.Index}', Code= '{item.Code}', BestBefore= '{item.BestBefore}'   ThreadID= '{Thread.CurrentThread.ManagedThreadId}'");

				//await Task.Delay(1000);
				Thread.Sleep(1000);
			}
		}
	}

	public async Task<bool> EventOut()
	{
		var result = await Task.Run(() => MyServerData.IsProductResult(77));
		return result;
		// return await Task.Run(() => MyServerData.IsProductResult(45)).Result;
	}
}

MyService MyServiceObject = new MyService();

private async void btnTASK_Click(object sender, EventArgs e)
{
	MyServiceObject = new MyService();
	await Task.Run(() => MyServiceObject.Process());

	// MessageBox.Show("TEST Mandelbrot Ready");
}

private void btnCancel_Click(object sender, EventArgs e)
{
	MyServiceObject.CurrentState = STATE.CANCEL;
}
Developer technologies | C#
Developer technologies | C#
An object-oriented and type-safe programming language that has its roots in the C family of languages and includes support for component-oriented programming.
{count} votes

Your answer

Answers can be marked as 'Accepted' by the question author and 'Recommended' by moderators, which helps users know the answer solved the author's problem.