C
C#13mo ago
viper

C# noob, trying to do a GUI app with a background service

Hello, what I am trying to do is: - Have a background connection to KSP (game) through a RPC library. - Plot live data coming from the connection I've used the WPF template from Rider, as it is the first one to choose from. At the moment I am trying to figure out how to have this background thread that updates the graph (using ScottPlot) This main loop is here: https://github.com/viperML/KspAutopilot/blob/2ad64786e8dd1bdb6457bf0b4e278b40b76b191e/MainWindow.xaml.cs Right now it "works", but closing window crashes with:
Unhandled exception. System.Threading.Tasks.TaskCanceledException: A task was canceled.
at System.Windows.Threading.DispatcherOperation.Wait(TimeSpan timeout)
at System.Windows.Threading.Dispatcher.InvokeImpl(DispatcherOperation operation, CancellationToken cancellationToken, TimeSpan timeout)
at System.Windows.Threading.Dispatcher.Invoke(Action callback, DispatcherPriority priority, CancellationToken cancellationToken, TimeSpan timeout)
at System.Windows.Threading.Dispatcher.Invoke(Action callback)
at KspAutopilot.MainWindow.Work(Object sender, EventArgs e) in C:\Users\ayats\Documents\KspAutopilot\MainWindow.xaml.cs:line 45
at System.Threading.Tasks.Task.<>c.<ThrowAsync>b__128_1(Object state)
at System.Threading.QueueUserWorkItemCallback.Execute()
at System.Threading.ThreadPoolWorkQueue.Dispatch()
at System.Threading.PortableThreadPool.WorkerThread.WorkerThreadStart()
Unhandled exception. System.Threading.Tasks.TaskCanceledException: A task was canceled.
at System.Windows.Threading.DispatcherOperation.Wait(TimeSpan timeout)
at System.Windows.Threading.Dispatcher.InvokeImpl(DispatcherOperation operation, CancellationToken cancellationToken, TimeSpan timeout)
at System.Windows.Threading.Dispatcher.Invoke(Action callback, DispatcherPriority priority, CancellationToken cancellationToken, TimeSpan timeout)
at System.Windows.Threading.Dispatcher.Invoke(Action callback)
at KspAutopilot.MainWindow.Work(Object sender, EventArgs e) in C:\Users\ayats\Documents\KspAutopilot\MainWindow.xaml.cs:line 45
at System.Threading.Tasks.Task.<>c.<ThrowAsync>b__128_1(Object state)
at System.Threading.QueueUserWorkItemCallback.Execute()
at System.Threading.ThreadPoolWorkQueue.Dispatch()
at System.Threading.PortableThreadPool.WorkerThread.WorkerThreadStart()
Feel free to recommend any alternative to WPF or ScottPlot, as I just wanted to try the language as an alternative to python/matplotlib
33 Replies
Omnissiah
Omnissiah13mo ago
first, you don't need Task.Run or better, you don't have any await in your code so i guess you do it because you want a thread...? also if you're using xaml you don't need to have async void your method can be async Task
Unknown User
Unknown User13mo ago
Message Not Public
Sign In & Join Server To View
viper
viperOP13mo ago
catch what? ok, so I have moved the project WPF -> Avalonia, and changed to async Task: https://github.com/viperML/KspAutopilot/blob/d1e667c86cfdc43c77d40e49b0663f173018354a/MainWindow.axaml.cs also, connection was IDisposable and rider didn't tell me about it, so I didn't have using (I believe it was causing the connection to linger and not exiting the app) this thing seems to work (?), and when I close the window it terminates though I don't know if I am doing something wrong still
Unknown User
Unknown User13mo ago
Message Not Public
Sign In & Join Server To View
viper
viperOP13mo ago
I don't know what you are saying about connection cut, I don't care about it I just wanted that closing the window would terminate the task and cleanup any resources cleanly
Omnissiah
Omnissiah13mo ago
i'm not entirely sure but i think in this situation _ = Work() should do it still worth a try or even better, pass a cancellationToken to it
Unknown User
Unknown User13mo ago
Message Not Public
Sign In & Join Server To View
Omnissiah
Omnissiah13mo ago
exactly, that's why i pointed out that there is really no async code in there
Unknown User
Unknown User13mo ago
Message Not Public
Sign In & Join Server To View
Omnissiah
Omnissiah13mo ago
yeah, but at that point i would remove task.delay and make everything sync
Unknown User
Unknown User13mo ago
Message Not Public
Sign In & Join Server To View
Omnissiah
Omnissiah13mo ago
it changes that at least you know it's not really an async method
Unknown User
Unknown User13mo ago
Message Not Public
Sign In & Join Server To View
Omnissiah
Omnissiah13mo ago
you can do all that in a sync method except for task.delay which would be the usual thread.sleep
Unknown User
Unknown User13mo ago
Message Not Public
Sign In & Join Server To View
MODiX
MODiX13mo ago
TeBeCo
I would still use await Task.Delay i would add a CTS and properly try/catch + call cancel and properly disconnect
React with ❌ to remove this embed.
Omnissiah
Omnissiah13mo ago
ah wait that's true (although wouldn't a 100 msec sleep be a tragedy)
Unknown User
Unknown User13mo ago
Message Not Public
Sign In & Join Server To View
Omnissiah
Omnissiah13mo ago
i don't agree entirely, the matter to me is explicitness if you hide that this is not really an async method and you don't tell that this would have that kind of consequences (sync i/o), then make it sync and make a thread if for example the call connection.SpaceCenter(); had been async (and no i/o stuff in the ctor), then this _ = WorkAsync() would have been good OR name the method in a way that everyone understands this has to be started in a background thread
Unknown User
Unknown User13mo ago
Message Not Public
Sign In & Join Server To View
viper
viperOP13mo ago
the C# is the reference implementation of KRPC, so I thought about using C# instead of going with the third-party ones
Unknown User
Unknown User13mo ago
Message Not Public
Sign In & Join Server To View
viper
viperOP13mo ago
though I agree it's weird, and I have other problems with it
Unknown User
Unknown User13mo ago
Message Not Public
Sign In & Join Server To View
viper
viperOP13mo ago
it's old as fuck though yeah
Unknown User
Unknown User13mo ago
Message Not Public
Sign In & Join Server To View
viper
viperOP13mo ago
the 3rd-party rust libs also use a sync RPC connection, and not Futures so yeah
Omnissiah
Omnissiah13mo ago
that's why i said "if the first line was an async call..."
Unknown User
Unknown User13mo ago
Message Not Public
Sign In & Join Server To View
viper
viperOP13mo ago
I don't know how to do any of that, so I would be grateful if you point out some documentation about those I'll look for the documentation myself meanwhile
MODiX
MODiX13mo ago
TeBeCo
var cts = new CancellationTokenSource();
_ = Task.Run(async () => await WorkAsync(cts.Token))


/********************************************************/
// if you want to stop the taks:
cts.Cancel(); //will throw a TaskCancelledException, which is also an OperationCanceledException where it's using inside an await call, like the await Task.Delay(...., ct)
/********************************************************/

private async Task WorkAsync(CancellationToken ct)
{
try
{
//the loop:
while(!ct.IsCancellationRequested)
{
//the delay:
await Task.Delay(duration, ct);
}
}
catch(OperationCancelledException){} // for the cts.Cancel()
catch(Exception){} // for other exception
}
var cts = new CancellationTokenSource();
_ = Task.Run(async () => await WorkAsync(cts.Token))


/********************************************************/
// if you want to stop the taks:
cts.Cancel(); //will throw a TaskCancelledException, which is also an OperationCanceledException where it's using inside an await call, like the await Task.Delay(...., ct)
/********************************************************/

private async Task WorkAsync(CancellationToken ct)
{
try
{
//the loop:
while(!ct.IsCancellationRequested)
{
//the delay:
await Task.Delay(duration, ct);
}
}
catch(OperationCancelledException){} // for the cts.Cancel()
catch(Exception){} // for other exception
}
you could put a specific try/cach inside the loop itself if you want to handle re-connect
React with ❌ to remove this embed.
viper
viperOP13mo ago
plot twist: this could even be done un App.cs or turned into a Host builder and use an IHostedService
the mention doesn't reference any of that
Unknown User
Unknown User13mo ago
Message Not Public
Sign In & Join Server To View
Want results from more Discord servers?
Add your server