|
I have recently been doing some C++ for a change and seeing that picture with the IDE just knowing where something is referenced now fills me with wonder. .NET truly is a blessed world.
|
# ? Sep 8, 2020 19:57 |
|
|
# ? Jun 1, 2024 19:10 |
I'm lost and need some guidance. We're building an integration with a third party that uses JWTs to authenticate users. The tokens are signed using an x509 cert. When I use the System.IdentityModel.Tokens.Jwt package to generate a token, it adds an x5t header to the token. We need this to be an x5c header instead, as the third party will not support x5t signed tokens. I've been struggling to find a way to change how the token is signed with no luck. code:
|
|
# ? Sep 9, 2020 18:35 |
|
Munkeymon posted:
WTF I have every codelens option turned on and I'm not getting that. I also have roslynator installed. I wonder if some of the extensions are fighting with each other.
|
# ? Sep 10, 2020 01:07 |
|
Withnail posted:WTF I have every codelens option turned on and I'm not getting that. I also have roslynator installed. I wonder if some of the extensions are fighting with each other. Also ensure that you're looking at a Property and not a Field - the latter of which doesn't have that functionality OOB with CodeLens.
|
# ? Sep 10, 2020 06:11 |
|
Cuntpunch posted:Also ensure that you're looking at a Property and not a Field - the latter of which doesn't have that functionality OOB with CodeLens. which honestly infuriates me no end
|
# ? Sep 10, 2020 07:05 |
|
Polio Vax Scene posted:I'm lost and need some guidance. I don't have an answer for you, but I just want to say Stay Strong my friend. I've been down similar cert-related rabbit holes before, and the lack of usable documentation and sane interfaces is a real buzzkill
|
# ? Sep 10, 2020 14:48 |
|
Polio Vax Scene posted:I'm lost and need some guidance. We're building an integration with a third party that uses JWTs to authenticate users. The tokens are signed using an x509 cert. There isn't a way to force the JwtSecurityToken class to add the x5c header. The good (?) news is that JwtHeader is a subclass of Dictionary<string, object>, so you can add the x5c header yourself as an array of strings, and it will be serialized correctly when you turn the token object into a JWT.
|
# ? Sep 10, 2020 16:15 |
Yep, the third party engineer was very helpful and was able to provide a sample. So below is my x5c header token code, for posterity.code:
|
|
# ? Sep 10, 2020 18:25 |
|
I thought I understood async/await in C#, but apparently not. I have a WinForm that displays a selected PDF and calls a bunch web API endpoints asynchronously based on the result of an OCR operation on the PDF. Since all of this takes 3-4 seconds to complete, I created a simple "Loading..." Form that displays a message to the user before I start the async web calls and closes itself when everything is done. This loading form has no code in it. It just displays a label with a message to wait. code:
This is the code in Op.ProcessImageDocAsync: code:
Secx fucked around with this message at 16:49 on Sep 14, 2020 |
# ? Sep 14, 2020 16:43 |
|
Are you doing something that takes a long time synchronously in one of the methods you're awaiting without starting it in a separate thread? Edit: Specifically are you doing the OCR operation synchronously? mystes fucked around with this message at 16:55 on Sep 14, 2020 |
# ? Sep 14, 2020 16:52 |
|
Yeah curious what that show() method is doing -- there' s no reason based on the code you shared it shouldn't work to display the loading and labels.
|
# ? Sep 14, 2020 17:13 |
|
mystes posted:Edit: Specifically are you doing the OCR operation synchronously? Yes, I'm doing three OCR operations (using Tesseract) by calling a synchronous method. To rule out issues with the OCR part, I commented out everything in Op.ProcessImageDocAsync before I call my GetCaseIdByOfficialNumberAsync. I just replaced calls to every method with hard coded values, but I can still observe the same issue. If I put a break point inside my method, the main form's pdfViewer control and my loading form text label are blank up until GetCaseIdByOfficialNumberAsync returns. GetCaseIdByOfficialNumberAsync doesn't do anything fancy (it doesn't do anything UI related). It uses HttpClient to call an API endpoint asynchronously, parses the JSON result and returns a Task<int>. quote:Yeah curious what that show() method is doing Literally nothing. It's just a WinForm with a hard coded label text that I am showing on the screen.
|
# ? Sep 14, 2020 18:42 |
|
Secx posted:Yes, I'm doing three OCR operations (using Tesseract) by calling a synchronous method. To rule out issues with the OCR part, I commented out everything in Op.ProcessImageDocAsync before I call my GetCaseIdByOfficialNumberAsync. I just replaced calls to every method with hard coded values, but I can still observe the same issue. If I put a break point inside my method, the main form's pdfViewer control and my loading form text label are blank up until GetCaseIdByOfficialNumberAsync returns. If you're blocking the thread with the OCR operations, the form won't be able to get repainted, and similarly, if you break from that method the control won't get returned to the event loop before the breakpoint so it won't get repainted before execution breaks. Whether you use async stuff or not, you need to be absolutely sure that you aren't tying up the gui thread during the OCR operations. If the methods actually block rather than simply awaiting something that's happening in another thread, you need to run them in another thread. If you replace your calls with "await Task.Delay(10000);" does the form get repainted properly (I believe this should actually return to the event loop while it's waiting)? mystes fucked around with this message at 18:55 on Sep 14, 2020 |
# ? Sep 14, 2020 18:51 |
|
Thanks, I'm gonna investigate it some more later tonight. In the meantime, I created a new dummy method to try Task.Delay.code:
code:
My GetCaseIdByOfficialNumberAsync method is basically this: code:
|
# ? Sep 14, 2020 19:28 |
|
I think i'm still missing something here but if you run with configureAwait(false) on your getcaseidbyofficialnumber do you have the same behavior?
|
# ? Sep 14, 2020 19:43 |
|
Secx posted:If I put a breakpoint on the await GetCaseIdByOfficialNumber line, my loadingForm label is blank until the async method returns just like before. If I comment out this line and put a breakpoint on the await Task.Delay(10000) line instead, then the loadingForm label is displayed and visible as expected. If you breakpoint immediately after your .Show() is called then it won't have had a chance to return to the event loop and handle all of the drawing events to draw the text on your label, so it's definitely expected to be blank/grey in that situation.
|
# ? Sep 14, 2020 20:59 |
|
One of the reasons why async/await can be so confusing is because it'll run synchronously (this is known as the "fast path" if you want to read up on it) all the way until it actually hits something where it has to wait for a completion. So if you have a costly or slow synchronous call in an async method, but nothing actually trigger it's... asynchronicity? it won't act especially nice. You could wrap the sync method in something like await Task.Run(stuff) or put an await Task.Yield just before it and it may behave a little better for you.
|
# ? Sep 14, 2020 21:02 |
|
rarbatrol posted:One of the reasons why async/await can be so confusing is because it'll run synchronously (this is known as the "fast path" if you want to read up on it) all the way until it actually hits something where it has to wait for a completion. So if you have a costly or slow synchronous call in an async method, but nothing actually trigger it's... asynchronicity? it won't act especially nice. You could wrap the sync method in something like await Task.Run(stuff) or put an await Task.Yield just before it and it may behave a little better for you. The way I describe it is that it's running synchronously right up until it hits an await. When it hits an await, it says "i'm going to be busy for a bit, so you can continue to do other stuff in the meantime like continue pumping messages through the message loop and keeping the UI responsive". That's not exactly, 100% textbook accurate, but it's close enough for most people to establish a decent mental model for what's going on.
|
# ? Sep 14, 2020 21:21 |
|
New Yorp New Yorp posted:The way I describe it is that it's running synchronously right up until it hits an await. When it hits an await, it says "i'm going to be busy for a bit, so you can continue to do other stuff in the meantime like continue pumping messages through the message loop and keeping the UI responsive". That's not exactly, 100% textbook accurate, but it's close enough for most people to establish a decent mental model for what's going on.
|
# ? Sep 14, 2020 21:26 |
|
rarbatrol posted:You could wrap the sync method in something like await Task.Run(stuff) or put an await Task.Yield just before it and it may behave a little better for you. await Task.Yield(); might be useful in an environment without a synchronization context, but here, if there's something running synchronously behind the scenes in HttpClient or something (which I've heard tell is the case in at least some versions of .NET), it won't do anything because the synchronization context will schedule the continuation on the UI thread and might even give it a higher priority than processing inputs and window messages.
|
# ? Sep 14, 2020 21:47 |
|
Right, and while there are many reasons to avoid using Task.Run, an OCR job sounds like a perfect fit.
|
# ? Sep 14, 2020 21:52 |
|
New Yorp New Yorp posted:The way I describe it is that it's running synchronously right up until it hits an await. When it hits an await, it says "i'm going to be busy for a bit, so you can continue to do other stuff in the meantime like continue pumping messages through the message loop and keeping the UI responsive". That's not exactly, 100% textbook accurate, but it's close enough for most people to establish a decent mental model for what's going on. I was a big fan of this explanation until I ran into a case where the code stayed synchronous through an await and had to explain it to someone (and myself). I'm still trying to find a replacement for it other than "await is like return except sometimes it isn't."
|
# ? Sep 15, 2020 04:09 |
|
At work I like to use a sort of mashup of a hot potato and Shrödinger's cat analogy, both in terms of whether there will be an async callback vs a synchronous return value, and whether the awaited task throws an exception. The await keyword does a lot of stuff.
|
# ? Sep 15, 2020 04:29 |
|
Async/await: its usually on another thread except when it isnt* * isnt: the compiler says so. usually cpu bound code or you don't await something in the called method * you call .result * you are writing a wpf or windows form app that makes use of synchronization context
|
# ? Sep 15, 2020 05:53 |
|
adaz posted:Async/await: its usually on another thread except when it isnt* Calling .Result doesn't affect which thread the task runs on. It just blocks the current thread and puts it to sleep until the task is done. The task itself will keep running wherever it needs to, which can really gently caress you in a single-threaded synchronization context like WPF or WinForms because it's a recipe to deadlock -- the task you're waiting on might require the same thread you just blocked to wait for it. That's why library authors are encouraged to use ConfigureAwait; because it frees them from accidentally contributing to a deadlock in the event that a consumer of the library uses .Result. (Don't ever use .Result. Not just because you break the whole idea of asynchronous processing if you're blocking threads, but because you should be calling .GetAwaiter().GetResult() instead; which does exactly the same thing as .Result except it doesn't wrap any exceptions the task throws inside an AggregateException, you just get the raw exception instead.)
|
# ? Sep 15, 2020 10:49 |
|
biznatchio posted:Calling .Result doesn't affect which thread the task runs on. It just blocks the current thread and puts it to sleep until the task is done. The task itself will keep running wherever it needs to, which can really gently caress you in a single-threaded synchronization context like WPF or WinForms because it's a recipe to deadlock -- the task you're waiting on might require the same thread you just blocked to wait for it. This is good to learn about. On a previous project I was faced with a need (well, not a need, but it seemed like the right way to go) to make some synchronous functionality async. But there were existing consumers of the synchronous API that I didn't want to interfere with, but I also didn't want to have two versions of the code. So I ended up writing a TaskExtensions class so that if you had a Task t you could do t.Wait_RethrowingOriginalException() or if you had a Task<T> t you could do result = t.Result_RethrowingOriginalException(). The *_RethrowingOriginalException() methods weren't very big but they had to mess around with ExceptionDispatchInfo in order to throw the inner exception of an AggregateException with its original stack trace. If I'm understanding correctly, a better way would have been GetAwaiter().GetResult()? Although I notice that in the docs for Task.GetAwaiter it claims that "This method is intended for compiler use rather than for use in application code"
|
# ? Sep 15, 2020 11:24 |
|
Hammerite posted:Although I notice that in the docs for Task.GetAwaiter it claims that "This method is intended for compiler use rather than for use in application code" Yes please don’t un-idiomatically use compiler internals directly just to save three lines of error handling code.
|
# ? Sep 15, 2020 14:17 |
|
raminasi posted:Yes please don’t un-idiomatically use compiler internals directly just to save three lines of error handling code. Even better, you can just unwrap the AggregateException with a regular catch guard: code:
|
# ? Sep 15, 2020 14:53 |
|
New Yorp New Yorp posted:The way I describe it is that it's running synchronously right up until it hits an await. raminasi posted:I was a big fan of this explanation until I ran into a case where the code stayed synchronous through an await and had to explain it to someone (and myself). I'm still trying to find a replacement for it other than "await is like return except sometimes it isn't." The definitive explanation is "it runs synchronously right up until the first not-yet-completed await".
|
# ? Sep 15, 2020 20:08 |
|
ljw1004 posted:The definitive explanation is "it runs synchronously right up until the first not-yet-completed await". watching people puzzle out async for nearly the last decade must be getting close to physically painful for you
|
# ? Sep 15, 2020 20:48 |
|
I wish Microsoft would actually push Service Fabric instead of jumping on Kubernetes. Its really underrated.
|
# ? Sep 15, 2020 23:27 |
|
Calidus posted:I wish Microsoft would actually push Service Fabric instead of jumping on Kubernetes. Its really underrated. Old-days Microsoft would have. New-days Microsoft just says "eh, screw it, we lost the battle -- let's throw our support behind the winner".
|
# ? Sep 16, 2020 00:01 |
|
ljw1004 posted:The definitive explanation is "it runs synchronously right up until the first not-yet-completed await". Is there a way to determine whether an await is not-yet-completed just by looking at the code, though? Because that's the part that seems to be tricky. e: Ok this questions sounds dumb after I wrote it out. The motivating case here was someone who added a second await to a method that already had one that caused a deadlock higher in the call stack. I couldn't figure out a way to explain what was going on with anything more satisfactory than "yeah that happens sometimes." raminasi fucked around with this message at 00:05 on Sep 16, 2020 |
# ? Sep 16, 2020 00:01 |
|
raminasi posted:Is there a way to determine whether an await is not-yet-completed just by looking at the code, though? Because that's the part that seems to be tricky. If i understood your problem right here any of the static code analysis tools - microsoft design rules, sonarqube - would've caught this and flagged it.
|
# ? Sep 16, 2020 00:09 |
|
adaz posted:If i understood your problem right here any of the static code analysis tools - microsoft design rules, sonarqube - would've caught this and flagged it. Then I'm not explaining it right. It was basically this: C# code:
|
# ? Sep 16, 2020 00:25 |
|
raminasi posted:Is there a way to determine whether an await is not-yet-completed just by looking at the code, though? Because that's the part that seems to be tricky. No there isn't... Consider "var t = Task.Delay(1000); await Task.Delay(1000); await t;". Is t completed or not at the point we await it? Can't tell. It depends on the vagaries of the scheduler and whatever else is going on. Consider "await Task.Delay(0);". Is this task completed or not at the point we await it? Can't tell. It depends on the internal implementation of the Task.Delay function. I don't know whether they wrote it to always return a not-yet-completed task which will get completed at the next time the event loop runs, or they wrote it to special-case the number 0 and return a completed task. It's usually a code smell if the correct functioning of the system depends on whether a task is already completed or not at point of completion. Here are two examples. (1) In an event API which only respects return values if they're returned synchronously, including indeed .NET events. This is a code smell because you shouldn't attach an async event handler to something which needs its work to be done synchronously. (2) In a multi-threaded sync context where the code after await might be on a different thread if the task hadn't yet completed. This is a code smell because you shouldn't depend on thread affinity in async code. quote:They added a second await to `AsyncThing`, which caused a deadlock. Yes, the code was wrong originally (which static analysis would have caught), but "combining .Wait() and await causes deadlocks" did not fly as an explanation when the code had already been doing that without deadlocking. Agreed, it's tough. The only answer is a more nuanced explanation. "Combining wait and async has the potential to cause deadlocks. You can sometimes prove that your code avoids the deadlock by a fragile manual whole-program analysis of invariants on every possible code-path. Or you can just ship it because it works right now, safe in the knowledge that it will randomly stop working at 3am in production one day, and will randomly stop working when a team member inadvertently breaks one of those undocumented invariants..." redleader posted:watching people puzzle out async for nearly the last decade must be getting close to physically painful for you Thanks! I actually instead love the questions, love that so many people are using it, love that Rust and C++ have come up with sophisticated faster+cleaner designers. I haven't yet seen any undergrad courses that cover async but I hope they'll come around eventually. ljw1004 fucked around with this message at 01:34 on Sep 16, 2020 |
# ? Sep 16, 2020 01:26 |
|
raminasi posted:Then I'm not explaining it right. It was basically this: Is it ok to do this? C# code:
|
# ? Sep 16, 2020 02:46 |
|
insta posted:Is it ok to do this? No you're fine. The real issue is if you start mixing in sync code - in the examples public void badbutworkedanyway() - and async calls. That has all sorts of very specific behavior that can easily cause deadlocks. In your scenario since you are using async/await "allthe way" up and down the stack you are a-ok. It's why the guidance from MS on all this is use async/await on everything from the entry point in the app all the way down to where its making db/http/whatever calls.
|
# ? Sep 16, 2020 02:54 |
|
How do I safely "get into" an async/await stack if I'm not in one to begin with?
|
# ? Sep 16, 2020 02:55 |
|
|
# ? Jun 1, 2024 19:10 |
|
insta posted:How do I safely "get into" an async/await stack if I'm not in one to begin with? That really depends on the use case and program you are writing. The easiest, and most general piece of advice, I can give is to use Task.Run which largely accomplishes what you want without deadlocking that I can think of. But you really shouldn't need to. Basically every modern framework (asp.net, wpf, winforms, even console apps now) provide async/await entry points so you'll probably need to be more specific with what you're doing, because task.run comes with some drawbacks.
|
# ? Sep 16, 2020 03:07 |