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
Bognar
Aug 4, 2011

I am the queen of France
Hot Rope Guy

Uziel posted:

Is this a good case to use async/await? Or is there a better way?

In a web application, async/await won't give you what you're looking for. The web server can only respond to a request once, so it's going to do that after all your awaited tasks have completed. Async/await on the server only helps with scalability.

If you still want to do this, I would suggest starting the report compilation process via Task.Run. Starting a task with Task.Run kicks it off on another thread, so it won't block returning the request. You should also pass in a Guid or unique Id to the compilation process. You can return that Id to the webpage where you can poll the server for changes to the compilation process.

Adbot
ADBOT LOVES YOU

ljw1004
Jan 18, 2005

rum

Bognar posted:

In a web application, async/await won't give you what you're looking for. The web server can only respond to a request once, so it's going to do that after all your awaited tasks have completed. Async/await on the server only helps with scalability.

If you still want to do this, I would suggest starting the report compilation process via Task.Run. Starting a task with Task.Run kicks it off on another thread, so it won't block returning the request. You should also pass in a Guid or unique Id to the compilation process. You can return that Id to the webpage where you can poll the server for changes to the compilation process.

Are you sure about that? I thought that ASP.NET is free to arbitrarily terminate all left-over "dangling" things (both threads started with Task.Run, and async methods that have been kicked off) after the response has been delivered to the user.

There is instead a specific ASP.NET way to continue doing "background work" after the response has been given. But I can't remember what it's called.

Dietrich
Sep 11, 2001

ljw1004 posted:

Are you sure about that? I thought that ASP.NET is free to arbitrarily terminate all left-over "dangling" things (both threads started with Task.Run, and async methods that have been kicked off) after the response has been delivered to the user.

There is instead a specific ASP.NET way to continue doing "background work" after the response has been given. But I can't remember what it's called.

This is absolutely true. While Task.Run will complete your action if the GC doesn't happen to be called during it's run, it may kill your action if the GC does happen to be called during your run.

There are lots of libraries to make this pretty simple though.

New Yorp New Yorp
Jul 18, 2003

Only in Kenya.
Pillbug
Can't you use QueueBackgroundWorkItem to ensure that it will run and not get GCed?

Dietrich
Sep 11, 2001

Ithaqua posted:

Can't you use QueueBackgroundWorkItem to ensure that it will run and not get GCed?

Yes, assuming the worker pool doesn't get recycled or something. Lots of the solutions you'll out there find include a persistence layer to ensure that the activity gets completed. I mean for a 2 second process you're probably fine with QueueBackgroundWorkItem, but you definitely want to plan for "what if it doesn't complete" with a cleanup job being ran periodically or something.

Uziel
Jun 28, 2004

Ask me about losing 200lbs, and becoming the Viking God of W&W.
Thanks all. I opted for just calling to a handler via javascript and returning the result as a callback.
I'll have a few more questions about another use case for async/await and I'll post them shortly.

Bognar
Aug 4, 2011

I am the queen of France
Hot Rope Guy

ljw1004 posted:

Are you sure about that? I thought that ASP.NET is free to arbitrarily terminate all left-over "dangling" things (both threads started with Task.Run, and async methods that have been kicked off) after the response has been delivered to the user.

To my knowledge, it's a bit stickier than that. ASP.NET Web Forms could kill started threads, and sometimes even your current thread if you call Response.End. ASP.NET MVC is a lot more lenient and will allow threads to run without killing them. However, the ASP.NET worker process will unload applications if they aren't receiving any requests. If you are using Task.Run, then ASP.NET doesn't know about your long-running task so it will kill your thread when the application is unloaded. With a ~2 second background process kicked off after a request, I don't think this is something to worry about. Other things that can cause an AppDomain teardown are modifying web.config or being force recycled by IIS (happens a bit less than once a day by default).

As others have mentioned, you can use QueueBackgroundWorkItem to make ASP.NET aware of your task, which has the advantage of trying to delay an AppDomain recycle or shutdown. However, it's not bullet-proof. I believe that recycling or shutting down will wait around 90 seconds before continuing regardless of background task status. If you want something truly reliable, put together a background processor that runs as part of a separate process or use a library like Hangfire.

Regardless, I should stop recommending Task.Run since QueueBackgroundWorkItem does the same thing but better.

Uziel
Jun 28, 2004

Ask me about losing 200lbs, and becoming the Viking God of W&W.
OK, the second use case is a web forms page. Again on button push, the code takes a list of objects, makes an API call, and then two database calls. My thoughts were toward using async/await for paralleism. This is basically what it looks like:

code:
 public void GetStatus()
 {
	foreach (var builder in builders)
	{
		//API Call that updates builder object
		//Saves object to database
		//Compile reports
	}
}
//set a bunch of UI controls using data from each object

New Yorp New Yorp
Jul 18, 2003

Only in Kenya.
Pillbug

Uziel posted:

OK, the second use case is a web forms page. Again on button push, the code takes a list of objects, makes an API call, and then two database calls. My thoughts were toward using async/await for paralleism. This is basically what it looks like:

code:
 public void GetStatus()
 {
	foreach (var builder in builders)
	{
		//API Call that updates builder object
		//Saves object to database
		//Compile reports
	}
}
//set a bunch of UI controls using data from each object

Async/await is not for parallelism. It's for asynchrony. They are different things. All this is going to do for you is return the thread to the thread pool while it's waiting for the database action to finish so that your web server can serve more requests. In a WinForms/WPF app, it would let the UI thread keep processing the message loop so that the UI would remain responsive. It wouldn't make things happen in parallel, or any faster.

Bognar
Aug 4, 2011

I am the queen of France
Hot Rope Guy
Well, that would be true if you awaited all the tasks in order. But you can kick off multiple long running asynchronous processes, then wait on all of them when Task.WhenAll. It's not necessarily parallelism (though it could be, depending on what thread the tasks resume on), but it is concurrency, and it can make your total execution faster.

Uziel
Jun 28, 2004

Ask me about losing 200lbs, and becoming the Viking God of W&W.

Ithaqua posted:

Async/await is not for parallelism. It's for asynchrony. They are different things. All this is going to do for you is return the thread to the thread pool while it's waiting for the database action to finish so that your web server can serve more requests. In a WinForms/WPF app, it would let the UI thread keep processing the message loop so that the UI would remain responsive. It wouldn't make things happen in parallel, or any faster.
Hm, I am not entirely concerned about the UI being responsive, mostly being faster. I did keep the UI responsive for a similar process in the equivalent WinForms app though.

Bognar
Aug 4, 2011

I am the queen of France
Hot Rope Guy

Uziel posted:

Hm, I am not entirely concerned about the UI being responsive, mostly being faster. I did keep the UI responsive for a similar process in the equivalent WinForms app though.

If your tasks are 100% independent from each other, including not relying on the same database connection, you can do something like this:

https://dotnetfiddle.net/DytvWm

However, this is only going to help you if you're waiting on some *asynchronous* action. This includes reading from a file, making a web request, calling to a database, etc. If you're doing 2 seconds worth of server-side processing, then you won't see any benefit.

EDIT: For example, see here:

https://dotnetfiddle.net/GxlLZO

Only 2 tasks get executed before hitting the 5 second limit because they're each spending 2 seconds of CPU time.

Bognar fucked around with this message at 19:26 on Sep 15, 2015

Uziel
Jun 28, 2004

Ask me about losing 200lbs, and becoming the Viking God of W&W.
Thanks, that's helpful. There is some waiting on the API calls and the database compilation.
Edit: Actually, one of the calls is a socket connection to a mainframe that takes ~30 seconds PER call and it's going to be called for each object in the list!

Uziel fucked around with this message at 20:12 on Sep 15, 2015

RICHUNCLEPENNYBAGS
Dec 21, 2010
edit: whoops, I should probably read better before posting.

epswing
Nov 4, 2003

Soiled Meat
SSMS:
code:
SELECT ROUND(811.9050, 2)
=> 811.9100
SELECT ROUND(CAST(811.9050 as decimal(18,2)), 2)
=> 811.91
.NET 4.5:
code:
decimal.Round(811.9050M, 2)
=> 811.90
My sanity is wavering as I furiously learn about MidpointRounding :v: :nms:

If I'm understanding this correctly, I should be using decimal.Round(value, 2, MidpointRounding.AwayFromZero) if I want my SQL rounding to match my C# rounding. Confirm/deny?

epswing fucked around with this message at 02:37 on Sep 16, 2015

Horn
Jun 18, 2004

Penetration is the key to success
College Slice

epalm posted:

SSMS:
code:
SELECT ROUND(811.9050, 2)
=> 811.9100
SELECT ROUND(CAST(811.9050 as decimal(18,2)), 2)
=> 811.91
.NET 4.5:
code:
decimal.Round(811.9050M, 2)
=> 811.90
My sanity is wavering as I furiously learn about MidpointRounding :v: :nms:

If I'm understanding this correctly, I should be using decimal.Round(value, 2, MidpointRounding.AwayFromZero) if I want my SQL rounding to match my C# rounding. Confirm/deny?

Yay bankers rounding. Ssrs does the latter by default as well.

Google Butt
Oct 4, 2005

Xenology is an unnatural mixture of science fiction and formal logic. At its core is a flawed assumption...

that an alien race would be psychologically human.

Was directed here after posting in the c thread:

Google Butt posted:

Hey guys, I've built a little program and gui in visual c# and wpf. How do I go about having a textbox/combobox remember the users last input after shutdown? Also, I'd like to add auto complete. I read that you can save something to the registry/a file.

I'm a super noob and I've built my program though Google, but I can't find anything on this, nothing I can understand anyway.

epswing
Nov 4, 2003

Soiled Meat

Horn posted:

Yay bankers rounding. Ssrs does the latter by default as well.

What's grinding my gears is SQL Server and C# do different things by default. Which project manager allowed that one?

The MUMPSorceress
Jan 6, 2012


^SHTPSTS

Gary’s Answer

Google Butt posted:

Was directed here after posting in the c thread:

Read about serialization and file streams and formatters. C#'s builtin support should be more than enough for a simple case like this.

ShimaTetsuo
Sep 9, 2001

Maximus Quietus

epalm posted:

What's grinding my gears is SQL Server and C# do different things by default. Which project manager allowed that one?

Probably the same one who allowed the same discrepancy between the rounding in Excel and in Excel-VBA. Microsoft get your poo poo TOGETHER

Bognar
Aug 4, 2011

I am the queen of France
Hot Rope Guy

Google Butt posted:

Was directed here after posting in the c thread:

You want to search for "saving state" and the myriad of things that can mean. For example: http://stackoverflow.com/questions/7522228/saving-state-between-program-restarts

The idea is that you're going to have values stored in something that lasts longer than your program process, e.g. a file on the hard drive. Save the values on application exit, or when the values are changed (if they're changed infrequently). Read the values when you start the application, then load them into the appropriate UI controls. WPF has events you can hook into for when the application is exiting.

Bognar
Aug 4, 2011

I am the queen of France
Hot Rope Guy

epalm posted:

What's grinding my gears is SQL Server and C# do different things by default. Which project manager allowed that one?

Microsoft teams don't (didn't?) communicate well, cf. all the CSV exporters in MS products that somehow don't work with Excel.

RICHUNCLEPENNYBAGS
Dec 21, 2010

Bognar posted:

Microsoft teams don't (didn't?) communicate well, cf. all the CSV exporters in MS products that somehow don't work with Excel.

My favorite Excel CSV thing is you can trick it into reading Unicode properly with a BOM or you can make it work across locales with the sep declaration, but you can't do both things at the same time.

SirViver
Oct 22, 2008

epalm posted:

Confirm/deny?
Confirmed.

When I discovered this I was also quite surprised that the default rounding mode used by .NET (ToEven) is not the "standard" rounding (AwayFromZero) everyone first learns in school.

But I also see how it can make sense. I guess it was decided to go this route as it by default reduces rounding errors when accumulating rounded values - a scenario that is rather likely to happen in business applications written by inexperienced developers. By comparison scientific applications will use full precision values anyway (or more realistically not use C# in the first place) and in most cases any rounding "defects" will be limited to the UI display.

raminasi
Jan 25, 2005

a last drink with no ice

Google Butt posted:

Was directed here after posting in the c thread:

For an actual location to save your state, check out isolated storage.

JawnV6
Jul 4, 2004

So hot ...

GrumpyDoctor posted:

For an actual location to save your state, check out isolated storage.
What's wrong with the Settings class linked in the first SO answer? I've used that before, seemed nice and friendly.

RICHUNCLEPENNYBAGS posted:

My favorite Excel CSV thing
Mine is flattening out long float values (millis-since-epoch) and losing the last 8 digits of precision, despite never saving or attempting to save the file.

Opulent Ceremony
Feb 22, 2012
I've got an issue that I hope someone can give me some ideas about. I've been hooking up a 3rd party vendor's webhooks to our own web application (that is, something event-worthy occurs with our data on their server, they send a POST request to our server to tell us about it) and I'm facing an issue in my staging environment that I didn't encounter in my dev.

This vendor sends a big pseudo base64-looking thing that contains a bunch of JSON and a JWS at the end. The JWS fails to validate every time (per their own SDK library I'm using, same one being used in both environments) on the staging server but never on my dev. Assuming they aren't doing something weird specifically for the requests going to our staging, failing JWS validation makes me think that somewhere along the way their POST body is getting modified by the staging server before it gets to the application level.

The dev server is IIS Express from VS2013, and staging is remotely hosted on Windows Server 2008 R2, IIS 7.5.

I've tried disabling any middleware-type things I could find that mess with requests (turned off UrlScan), and am fairly certain it isn't just truncating the POST data at a certain length. Also I'm just a developer and know very little about servers; we have an actual server admin here that is trying to look into this as well.

Any thoughts of where else to look or think about would be very helpful, thanks.

Bognar
Aug 4, 2011

I am the queen of France
Hot Rope Guy
Have you inspected the actual POST data to see if it looks like it's being modified? I'd be surprised if your server is doing any modification to it before it reaches your application. I'm more inclined to think that there's something environment specific in the JWS validation that's causing it to fail. Have you tried capturing a request to your staging server and running it through dev to see if the validation still fails?

raminasi
Jan 25, 2005

a last drink with no ice

JawnV6 posted:

What's wrong with the Settings class linked in the first SO answer? I've used that before, seemed nice and friendly.

Mine is flattening out long float values (millis-since-epoch) and losing the last 8 digits of precision, despite never saving or attempting to save the file.

I'd actually forgotten about that. It's great if your use case is sufficiently simple, but isolated storage is more versatile because you're not limited to a key-value store. (My recent use cases have not been sufficiently simple, which is why I forgot about it.)

Opulent Ceremony
Feb 22, 2012

Bognar posted:

Have you inspected the actual POST data to see if it looks like it's being modified? I'd be surprised if your server is doing any modification to it before it reaches your application. I'm more inclined to think that there's something environment specific in the JWS validation that's causing it to fail. Have you tried capturing a request to your staging server and running it through dev to see if the validation still fails?

Yes, I've inspected the POST from both dev and staging, and they don't look different as far as I can tell (this involves decoding it as base64 with a method that doesn't break on imperfect base64-encode), they both have a bunch of JSON that looks about the same and the JWS at the end. I agree that there being an environmental concern about the JWS validation should be considered, but not sure about what else I should be checking. I know IIS servers identify the .NET version (or is it the ASP.NET version) of their app pool, but I don't think that corresponds to the version of .NET that the application is running on, since the app pool is 4.0 something, and this application targets 4.5.2 and we don't have any issues.

Unfortunately I can't take a request captured on staging and run it through dev, because there is a different exception that gets thrown from the vendor library that occurs before the JWS fail exception (confirmed with ILDASM) if their timestamp is off system time. Maybe I can just change my dev system time to get around that and try to validate JWS that way.

Bognar
Aug 4, 2011

I am the queen of France
Hot Rope Guy
Well this is fun:

C# code:
// assume EST local timezone
var dst    = DateTime.Parse("2015-11-01T05:30:00Z");
var nonDst = DateTime.Parse("2015-11-01T06:30:00Z");
Console.WriteLine(dst);    // 11/1/2015 1:30:00 AM
Console.WriteLine(nonDst); // 11/1/2015 1:30:00 AM
Console.WriteLine(dst == nonDst); // true
DateTime.Parse automatically converts UTC times into local time and loses information in the case of daylight savings time.

Bognar fucked around with this message at 21:28 on Sep 17, 2015

EssOEss
Oct 23, 2006
128-bit approved

Opulent Ceremony posted:

this involves decoding it as base64 with a method that doesn't break on imperfect base64-encode

Do I understand this right that there is broken base64-encoded data coming in? Perhaps you need to ask the vendor to send valid data in that case?! Or am I misunderstanding what this means?

At any rate, can you manually validate the JWS? Might give you some clues, assuming you have all the input data available. Without access to the actual logic doing the data processing (I understand it is part of the vendor library), it might be hard to debug this - if you can't get this access, just file a support ticket with the vendor.

Bognar posted:

DateTime.Parse automatically converts UTC times into local time and loses information in the case of daylight savings time.

code:
01.11.2015 7:30.00
01.11.2015 8:30.00
False
I do not immediately understand what DST has to do with it but DST is active here and it does not appear to lose any information on my machine, so I am not sure what exactly you are seeing there. But you should always use DateTimeOffset anyway - DateTime is legacy garbage.

code:
01.11.2015 5:30.00 +00:00
01.11.2015 6:30.00 +00:00
False
Edit: oh, is that the time when DST starts in your locale? Yeah, I understand what you mean in that case. Still, legacy garbage!

EssOEss fucked around with this message at 21:48 on Sep 17, 2015

Opulent Ceremony
Feb 22, 2012

EssOEss posted:

Do I understand this right that there is broken base64-encoded data coming in?

I'm sorry, it looks like the data is a JWT, I thought it was base64-encoded because it looked like it and attempting to base64 decode provided mostly good results.

EssOEss posted:

At any rate, can you manually validate the JWS?

I tried putting in my data captures to http://jwt.io/ and neither validated there, even the data that the vendor library validated, so now I'm just more confused. Either way you are right, I'm in the process of talking to folks at the vendor company, still trying to jump through filtering hoops to find someone knowledgeable.

Edit: Probably didn't validate on that page since I didn't have the vendor secret!

Opulent Ceremony fucked around with this message at 21:59 on Sep 17, 2015

Sedro
Dec 31, 2008

Bognar posted:

Well this is fun:

C# code:
// assume EST local timezone
var dst    = DateTime.Parse("2015-11-01T05:30:00Z");
var nonDst = DateTime.Parse("2015-11-01T06:30:00Z");
Console.WriteLine(dst);    // 11/1/2015 1:30:00 AM
Console.WriteLine(nonDst); // 11/1/2015 1:30:00 AM
Console.WriteLine(dst == nonDst); // true
DateTime.Parse automatically converts UTC times into local time and loses information in the case of daylight savings time.
They are being represented local time, i.e. dst.Kind == DateTimeKind.Local. No information was lost because 5:30 is 6:30 in your time zone. You can either convert them to UTC
C# code:
var dst = TimeZoneInfo.ConvertTimeToUtc(DateTime.Parse("2015-11-01T05:30:00Z"));
var nonDst = TimeZoneInfo.ConvertTimeToUtc(DateTime.Parse("2015-11-01T06:30:00Z"));
or tell it to parse as UTC
C# code:
var dst = DateTime.Parse("2015-11-01T05:30:00Z", CultureInfo.InvariantCulture, DateTimeStyles.AdjustToUniversal);
var nonDst = DateTime.Parse("2015-11-01T06:30:00Z", CultureInfo.InvariantCulture, DateTimeStyles.AdjustToUniversal);

Bognar
Aug 4, 2011

I am the queen of France
Hot Rope Guy

Sedro posted:

They are being represented local time, i.e. dst.Kind == DateTimeKind.Local. No information was lost. You can either convert them to UTC

The example I provided shows that's not true, information is lost since 1:30AM when DST ends is ambiguous. The only way to avoid this with DateTime is with your third suggestion - specify to parse as UTC (or with RoundTripKind).

EDIT: Caught your edit:

Sedro posted:

No information was lost because 5:30 is 6:30 in your time zone.

How does that not count as losing information?

putin is a cunt
Apr 5, 2007

BOY DO I SURE ENJOY TRASH. THERE'S NOTHING MORE I LOVE THAN TO SIT DOWN IN FRONT OF THE BIG SCREEN AND EAT A BIIIIG STEAMY BOWL OF SHIT. WARNER BROS CAN COME OVER TO MY HOUSE AND ASSFUCK MY MOM WHILE I WATCH AND I WOULD CERTIFY IT FRESH, NO QUESTION
Am I understanding correctly that 5:30 is when DST takes effect? If so in effect there is no such thing as 5:30 for that date in your timezone, it's actually 6:30. The two date/times you've provided are identical. What information do you think you've lost? You asked C# for a DateTime that corresponds to the two identical points in time, and you got them?

JawnV6
Jul 4, 2004

So hot ...

The Wizard of Poz posted:

Am I understanding correctly that 5:30 is when DST takes effect? If so in effect there is no such thing as 5:30 for that date in your timezone, it's actually 6:30. The two date/times you've provided are identical.
No. A person in Arizona, which does not use DST, has two distinct times. My time zone calls two of them the same, but the Arizonan should be able to create both times and let them remain distinct, even if they're ssh'd into a Californian server.

putin is a cunt
Apr 5, 2007

BOY DO I SURE ENJOY TRASH. THERE'S NOTHING MORE I LOVE THAN TO SIT DOWN IN FRONT OF THE BIG SCREEN AND EAT A BIIIIG STEAMY BOWL OF SHIT. WARNER BROS CAN COME OVER TO MY HOUSE AND ASSFUCK MY MOM WHILE I WATCH AND I WOULD CERTIFY IT FRESH, NO QUESTION

JawnV6 posted:

No. A person in Arizona, which does not use DST, has two distinct times. My time zone calls two of them the same, but the Arizonan should be able to create both times and let them remain distinct, even if they're ssh'd into a Californian server.

I don't really know how else to explain it, other than those two date/time strings refer to the very same point in time because you are parsing them using your local timezone. You haven't lost any information, because they are literally the exact same point in time. If Event A occurred at 5:30 AM your time, then it occurred at the same point in time all over the world as Event B which occurred at 6:30 AM your time.

Re: your point about someone logging in from Arizona and entering those two date/times. If they do this, and they are referring to two distinct times, then that must mean they are entering Arizona date/times and you need to parse it with that in mind - or do what everyone else does and store date/times as UTC and convert to the users local time only for the purposes of display.

It might be that I'm on the completely wrong track here, I'm far from an expert on this.

putin is a cunt fucked around with this message at 23:26 on Sep 17, 2015

JawnV6
Jul 4, 2004

So hot ...

The Wizard of Poz posted:

You haven't lost any information, because they are literally the exact same point in time

No. They are an hour apart. One happens, then an hour goes by, and the second happens. They share a label, that doesn't magically collapse the space/time continuum between those events.

Adbot
ADBOT LOVES YOU

NihilCredo
Jun 6, 2011

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

Pause for a second. I thought DST always took effect at 2 AM <-> 3 AM?

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