Register a SA Forums Account here!
JOINING THE SA FORUMS WILL REMOVE THIS BIG AD, THE ANNOYING UNDERLINED ADS, AND STUPID INTERSTITIAL ADS!!!

You can: log in, read the tech support FAQ, or request your lost password. This dumb message (and those ads) will appear on every screen until you register! Get rid of this crap by registering your own SA Forums Account and joining roughly 150,000 Goons, for the one-time price of $9.95! We charge money because it costs us money per month for bills, and since we don't believe in showing ads to our users, we try to make the money back through forum registrations.
 
  • Post
  • Reply
EssOEss
Oct 23, 2006
128-bit approved
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.

Adbot
ADBOT LOVES YOU

Polio Vax Scene
Apr 5, 2009



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:
var certBytes = System.IO.File.ReadAllBytes("certificate.pfx");
var cert = new System.Security.Cryptography.X509Certificates.X509Certificate2(certBytes, "******");

var claims = new List<Claim>
{
    new Claim("sub", "test"),
};

var x509SigningCredentials = new X509SigningCredentials(cert);

JwtSecurityToken securityToken = new JwtSecurityToken(
    claims: claims,
    notBefore: DateTime.UtcNow,
    expires: DateTime.UtcNow.AddMinutes(60),
    signingCredentials: x509SigningCredentials);

Console.WriteLine(securityToken.Header.X5t); // No option for x5c in this class

Withnail
Feb 11, 2004

Munkeymon posted:


CodeLense does it

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.

Cuntpunch
Oct 3, 2003

A monkey in a long line of kings

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.

redleader
Aug 18, 2005

Engage according to operational parameters

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

epswing
Nov 4, 2003

Soiled Meat

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 :(

No Pants
Dec 10, 2000

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.
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.

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.

Polio Vax Scene
Apr 5, 2009



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:
var certBytes = System.IO.File.ReadAllBytes("certificate.pfx");
var cert = new System.Security.Cryptography.X509Certificates.X509Certificate2(certBytes, "******");

var claims = new List<Claim>
{
    new Claim("sub", "test"),
};

//Replaced with below
//var x509SigningCredentials = new X509SigningCredentials(cert);

                    RsaSecurityKey rsaSecurityKey = new RsaSecurityKey(cert.GetRSAPrivateKey());
                    var x509SigningCredentials = new SigningCredentials(rsaSecurityKey, SecurityAlgorithms.RsaSha512); ;

JwtSecurityToken securityToken = new JwtSecurityToken(
    claims: claims,
    notBefore: DateTime.UtcNow,
    expires: DateTime.UtcNow.AddMinutes(60),
    signingCredentials: x509SigningCredentials);

//This is the new x5c header stuff
                    X509Chain chain = new X509Chain();
                    chain.Build(cert);
                    List<string> x5cList = new List<string>();
                    foreach (var element in chain.ChainElements)
                    {
                        x5cList.Add(Convert.ToBase64String(element.Certificate.RawData));
                    }
                    securityToken.Header.Add("x5c", x5cList.ToArray());

Secx
Mar 1, 2003


Hippopotamus retardus
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:
            var pdfDocument = PdfDocument.Load(selectedPDFPath);
            pdfViewer1.Document = pdfDocument;
            pdfViewer1.Renderer.Visible = true; //Displays the PDF on my main form in the pdfViewer control

            frmLoading loadingForm = new frmLoading();
            loadingForm.Show(); //Shows a small form with a message about things happening

	    //pdfViewer control not displaying PDF and loadingForm label text still gray at this point

            await Op.ProcessImageDocAsync(selectedPDFPath); //A bunch of async calls
	    loadingForm.Close();
This sort-of works, but not as expected. My Loading form will be displayed, but the label text on the will be gray until the first async call in Op.ProcessImageDocAsync completes. Same for my PDF viewer control. It will only display the PDF once the first async call completes.

This is the code in Op.ProcessImageDocAsync:

code:
	public async Task ProcessImageDocAsync(string filePath) {
		...
		//Up until this point the PDFViewer control doesn't display the PDF and the Loading form's label is gray
                var caseId = await GetCaseIdByOfficialNumberAsync(officialNumber);
		//As soon as the above completes the PDFViewer control will show the PDF and the Loading label will be shown
                await GetInproCaseByCaseIdAsync(caseId);
		...

Secx fucked around with this message at 16:49 on Sep 14, 2020

mystes
May 31, 2006

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

adaz
Mar 7, 2009

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.

Secx
Mar 1, 2003


Hippopotamus retardus

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.

mystes
May 31, 2006

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.

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>.
It's really hard to tell just from your posts whether you're doing everything correctly and there's some other problem or whether you're misunderstanding how async stuff works.

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

Secx
Mar 1, 2003


Hippopotamus retardus
Thanks, I'm gonna investigate it some more later tonight. In the meantime, I created a new dummy method to try Task.Delay.

code:
        public async Task fooBarAsync()
        {
            var caseId = await GetCaseIdByOfficialNumberAsync("123456ABC");
            //await Task.Delay(10000);
            return;
        }
It is called from the main UI form:

code:
            frmLoading loadingForm = new frmLoading();
            loadingForm.Show(); //Shows a small form with a message about things happening

            await Op.fooBarAsync();
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.

My GetCaseIdByOfficialNumberAsync method is basically this:

code:
        public async Task<int> GetCaseIdByOfficialNumberAsync(string officialNumber)
        {

            var result = await _client.GetAsync($"/path/to/API/{ officialNumber }");
            var jsonString = await result.Content.ReadAsStringAsync();
            int caseId = 0;

            try
            {
                var o = JArray.Parse(jsonString);
                IEnumerable<JToken> j = o.SelectTokens("$.[*]");

                if (j.Count() > 1)
                {
                    //Some business logic to handle cases when there's more than one result in the json
                }
                else
                {
                    caseId = Convert.ToInt32(j.First()["id"]);

                }
            } catch (Exception e)
            {
                //Some exception handling
            }

            return caseId;
        }

adaz
Mar 7, 2009

I think i'm still missing something here but if you run with configureAwait(false) on your getcaseidbyofficialnumber do you have the same behavior?

beuges
Jul 4, 2005
fluffy bunny butterfly broomstick

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.

rarbatrol
Apr 17, 2011

Hurt//maim//kill.
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.

New Yorp New Yorp
Jul 18, 2003

Only in Kenya.
Pillbug

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.

mystes
May 31, 2006

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.
The point is that you can go through multiple levels of awaits without control returning to the message loop until you get to something that actually runs on a different thread.

No Pants
Dec 10, 2000

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.

rarbatrol
Apr 17, 2011

Hurt//maim//kill.
Right, and while there are many reasons to avoid using Task.Run, an OCR job sounds like a perfect fit.

raminasi
Jan 25, 2005

a last drink with no ice

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."

rarbatrol
Apr 17, 2011

Hurt//maim//kill.
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.

adaz
Mar 7, 2009

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

biznatchio
Mar 31, 2001


Buglord

adaz posted:

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

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.)

Hammerite
Mar 9, 2007

And you don't remember what I said here, either, but it was pompous and stupid.
Jade Ear Joe

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.

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.)

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"

raminasi
Jan 25, 2005

a last drink with no ice

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.

NihilCredo
Jun 6, 2011

iram omni possibili modo preme:
plus una illa te diffamabit, quam multæ virtutes commendabunt

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:
		try
		{
			var x = catchtest().Result;
		}
		catch(AggregateException e) when (e.InnerException is System.IO.FileNotFoundException) {		
			Console.WriteLine("got it");
		}

ljw1004
Jan 18, 2005

rum

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".

redleader
Aug 18, 2005

Engage according to operational parameters

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

Calidus
Oct 31, 2011

Stand back I'm going to try science!
I wish Microsoft would actually push Service Fabric instead of jumping on Kubernetes. Its really underrated.

New Yorp New Yorp
Jul 18, 2003

Only in Kenya.
Pillbug

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".

raminasi
Jan 25, 2005

a last drink with no ice

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

adaz
Mar 7, 2009

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.

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."

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.

raminasi
Jan 25, 2005

a last drink with no ice

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:
public async Task AsyncThing()
{
    await InnerCall(); // no ConfigureAwait but it worked anyway
}

public void BadButWorkedAnyway()
{
    AsyncThing().Wait();
}
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.

ljw1004
Jan 18, 2005

rum

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

insta
Jan 28, 2009

raminasi posted:

Then I'm not explaining it right. It was basically this:
C# code:
public async Task AsyncThing()
{
    await InnerCall(); // no ConfigureAwait but it worked anyway
}

public void BadButWorkedAnyway()
{
    AsyncThing().Wait();
}
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.

Is it ok to do this? :ohdear:
C# code:

public async Task AsyncThing()
{
   await InnerCall();
}

private async Task InnerCall()
{
   await LongThingy1();
   await LongThingy2();
}
Should I do it a different way?

adaz
Mar 7, 2009

insta posted:

Is it ok to do this? :ohdear:
C# code:

public async Task AsyncThing()
{
   await InnerCall();
}

private async Task InnerCall()
{
   await LongThingy1();
   await LongThingy2();
}
Should I do it a different way?

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.

insta
Jan 28, 2009
How do I safely "get into" an async/await stack if I'm not in one to begin with?

Adbot
ADBOT LOVES YOU

adaz
Mar 7, 2009

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.

  • 1
  • 2
  • 3
  • 4
  • 5
  • Post
  • Reply