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
Inverness
Feb 4, 2009

Fully configurable personal assistant.
The more I think about it the more I don't like the idea of parameterless constructors for structs. I think the inconsistency between that and all of the other places where structs are default initialized will just create confusion and mistakes.

The inability to make a parameterless constructor made it explicit that default initialization for structs was rightly beyond your control and you had to deal with that in your code.

If you really wanted a default state without having to supply arguments you always have the option of static methods.

Adbot
ADBOT LOVES YOU

ljw1004
Jan 18, 2005

rum

Inverness posted:

The more I think about it the more I don't like the idea of parameterless constructors for structs. I think the inconsistency between that and all of the other places where structs are default initialized will just create confusion and mistakes.

The inability to make a parameterless constructor made it explicit that default initialization for structs was rightly beyond your control and you had to deal with that in your code.

If you really wanted a default state without having to supply arguments you always have the option of static methods.

I understand these concerns. But let me motivate the other side of the story...

The new VB compiler (written in VB) is 50% faster than the old one (written in C++). The new C# compiler is about as fast as the old one, but general C# responsiveness has got better. These results might be surprising to people who think that C++ is generally faster. We got better perf because (1) it's safer for a team to optimize algorithms+datastructures in a higher-level language, (2) we switched to immutability throughout which helps it use multiple cores better, (3) we were careful to avoid unnecessary allocations, since they're the biggest slowdown in most .NET apps. Or rather: allocations are almost free, but it's the garbage-collection hangover afterwards that's the problem.

code:
var x = new List<int>();
Console.WriteLine(x.Length); // prints "0"

var y = new ImmutableArray<int>();
Console.WriteLine(y.Length); // throws NullReferenceException ??!?
Why does the ImmutableArray throw a NullReferenceException?

One of the ways to reduce unnecessary allocations is using structs rather than classes. ImmutableArray happens to be a struct, but it's very easy not to notice that fact. With the addition of parameterless struct ctors we can make the above code work as you'd expect, i.e. more consistently with classes.


It's a tradeoff. We can add the feature and get consistency in some use-cases. Or we can leave things as-is and get consistency in other cases. The question boils down to a judgment call about which use-cases are more valuable.




Unrelated: I'm having fun with animated gifs and the new language features...

and another:

and another:

and another:


We've been calling ?. the "elvis" operator because it looks like two eyes with a quiff of hair. Maybe "Tintin operator" would be a better name.

Wikipedia claims that the null-coalescing operator is the one that's called Elvis because it's written ?: in PHP, and if you look sideways then ?:j looks like Elvis with a smirk.

ljw1004 fucked around with this message at 21:45 on Nov 23, 2014

Inverness
Feb 4, 2009

Fully configurable personal assistant.

ljw1004 posted:

code:
var x = new List<int>();
Console.WriteLine(x.Length); // prints "0"

var y = new ImmutableArray<int>();
Console.WriteLine(y.Length); // throws NullReferenceException ??!?
Why does the ImmutableArray throw a NullReferenceException?

One of the ways to reduce unnecessary allocations is using structs rather than classes. ImmutableArray happens to be a struct, but it's very easy not to notice that fact. With the addition of parameterless struct ctors we can make the above code work as you'd expect, i.e. more consistently with classes.


It's a tradeoff. We can add the feature and get consistency in some use-cases. Or we can leave things as-is and get consistency in other cases. The question boils down to a judgment call about which use-cases are more valuable.
If ImmutableArray is throwing a NullReferenceException that seems like a problem in the design of the property and struct as opposed to how structs are handled in general. If your struct isn't aware of all-zeroed being a valid state I consider that an issue unless you're explicit about not doing that (which isn't really a good solution anyways). You can get consistency in the example you cited without changing language behavior, which is why I'm not in favor of that change.

Gul Banana
Nov 28, 2003

ah, so that's why immutablearray was removed from the first public release of bcl.immutablecollections...

RICHUNCLEPENNYBAGS
Dec 21, 2010

bpower posted:

Any objections to using EF for the simple crud stuff, and use something else (PetaPoco maybe) for reports/graphs/import/export etc

Or should I just pick one and stick with it.

You should probably pick one but in my experience the kind of EF that makes sense for readonly stuff and the kind that makes sense for CRUD are different (I usually select into intermediate representations for readonly pages with multiple entities or whatever to avoid lazy loading or neverending queries but for updating an entity I work with the entity classes directly).

The people telling you to beware of lazy loading are right, though.

Essential
Aug 14, 2003

ljw1004 posted:

Unrelated: I'm having fun with animated gifs and the new language features...

and another:

and another:

and another:


This is awesome! I have many VB apps that have IsNot Nothing all over the place. This would be a really cool feature to have!

Funking Giblet
Jun 28, 2004

Jiglightful!

RICHUNCLEPENNYBAGS posted:

You should probably pick one but in my experience the kind of EF that makes sense for readonly stuff and the kind that makes sense for CRUD are different (I usually select into intermediate representations for readonly pages with multiple entities or whatever to avoid lazy loading or neverending queries but for updating an entity I work with the entity classes directly).

The people telling you to beware of lazy loading are right, though.

If you don't use Lazy Loading, use a basic ORM. We use Lazy Loading here, problems arise when there is a fundamental misunderstanding of how the ORM works. A little knowledge and it's no longer a problem. You should be using projections on reads, lazy loading on writes. (Left outer joins will prevent lazy loading if you know what you need ahead of time).

Jewel
May 2, 2009

Question: Python lets you use ", ".Join(array), but why doesn't .NET?



It lets me call the function Join, which is strange because if you call a static function on any other instance it gives you an error saying "don't call a static on an instance", so why is string exempt?

zokie
Feb 13, 2006

Out of many, Sweden

Jewel posted:

Question: Python lets you use ", ".Join(array), but why doesn't .NET?



It lets me call the function Join, which is strange because if you call a static function on any other instance it gives you an error saying "don't call a static on an instance", so why is string exempt?

Try fixing the other error and you'll get the expected behavior. The compiler is confused about what to do with an array of numbers when it expects strings...

Jewel
May 2, 2009

zokie posted:

Try fixing the other error and you'll get the expected behavior. The compiler is confused about what to do with an array of numbers when it expects strings...

No, string.Join(string, int[]) works absolutely fine because it converts each int to a string. The problem is "SOME STRING".Join(string, int[]) is the exact same as the above, though of course the initial "SOME STRING" is completely disregarded.

",".Join(arr) is erroring because it's looking for the joining string as a first argument, but I'm just wondering why you can even call it that way in the first place.

RICHUNCLEPENNYBAGS
Dec 21, 2010

Funking Giblet posted:

If you don't use Lazy Loading, use a basic ORM. We use Lazy Loading here, problems arise when there is a fundamental misunderstanding of how the ORM works. A little knowledge and it's no longer a problem. You should be using projections on reads, lazy loading on writes. (Left outer joins will prevent lazy loading if you know what you need ahead of time).

Well, yeah, OK... what I really mean is don't allow lazy loading to happen in a loop. Projections on reads and lazy loading on writes is sensible. Judicious use of the load method can reduce the need for lazy loading a lot though.

Jewel posted:

Question: Python lets you use ", ".Join(array), but why doesn't .NET?



It lets me call the function Join, which is strange because if you call a static function on any other instance it gives you an error saying "don't call a static on an instance", so why is string exempt?

This is a famously unintuitive behavior of Python; why would .NET be the same? You can write an extension method to do it if you want.

code:
public static string MyJoin (this string joiner, params string[] args) 
  {
    return string.Join(joiner, args);
  }

RICHUNCLEPENNYBAGS fucked around with this message at 14:43 on Nov 25, 2014

Jewel
May 2, 2009

RICHUNCLEPENNYBAGS posted:

Well, yeah, OK... what I really mean is don't allow lazy loading to happen in a loop. Projections on reads and lazy loading on writes is sensible. Judicious use of the load method can reduce the need for lazy loading a lot though.


This is a famously unintuitive behavior of Python; why would .NET be the same? You can write an extension method to do it if you want.

code:
public static string MyJoin (this string joiner, params string[] args) 
  {
    return string.Join(joiner, args);
  }

A better method would probably be a .Join on an IEnumerable, actually. So I could just go intArray.Join(", "). I might make that later.

SirViver
Oct 22, 2008

Jewel posted:

Question: Python lets you use ", ".Join(array), but why doesn't .NET?



It lets me call the function Join, which is strange because if you call a static function on any other instance it gives you an error saying "don't call a static on an instance", so why is string exempt?
String isn't exempt; "abc".Join(...) does not make a call to String.Join(string, string[]) but instead picks up the LINQ extension method Join(...) (used for joining elements in a SQL-like fashion), since a string is an IEnumerable<char>.

Jewel posted:

No, string.Join(string, int[]) works absolutely fine because it converts each int to a string.
Also no, an int[] is definitely not auto-converted to a string[]. Where did you get that idea from? :psyduck:

E: Disregard this - I didn't realize newer .NET versions added a different overload of String.Join.

SirViver fucked around with this message at 16:54 on Nov 25, 2014

Bognar
Aug 4, 2011

I am the queen of France
Hot Rope Guy

SirViver posted:

Also no, an int[] is definitely not auto-converted to a string[]. Where did you get that idea from? :psyduck:

The quote was "it converts each int to a string", which to me doesn't imply array type conversion. It's also not incorrect, since string.Join(string, int[]) will use the string.Join(string, IEnumerable<T>) overload, which calls .ToString on every element.

SirViver
Oct 22, 2008

Bognar posted:

The quote was "it converts each int to a string", which to me doesn't imply array type conversion. It's also not incorrect, since string.Join(string, int[]) will use the string.Join(string, IEnumerable<T>) overload, which calls .ToString on every element.
Ahh sorry, my mistake. I'm still stuck in a VS2010/.NET 3.5 mindset, as that's what I have to use at work. Didn't realize they added a new overload.

Bognar
Aug 4, 2011

I am the queen of France
Hot Rope Guy

SirViver posted:

Ahh sorry, my mistake. I'm still stuck in a VS2010/.NET 3.5 mindset, as that's what I have to use at work.

:ohdear: You have my sympathy.

epswing
Nov 4, 2003

Soiled Meat
I'm confused about where C# ends and html begins in ASP.NET Razor views. I'd like to write a @helper which takes a string and replaces spaces with non-breaking html spaces. How do I accomplish this?

code:
@helper NonBreakingSpace(string s)
{
    <text>@s.Replace(" ", "& nbsp;")</text>
}
This won't work because razor will helpfully protect me and output "& ampnbsp;"

Edit: OK, this is hard to talk about on The Internet :v:. Pretend there aren't spaces after the ampersands above.

epswing fucked around with this message at 19:28 on Nov 25, 2014

Munkeymon
Aug 14, 2003

Motherfucker's got an
armor-piercing crowbar! Rigoddamndicu𝜆ous.



epalm posted:

I'm confused about where C# ends and html begins in ASP.NET Razor views. I'd like to write a @helper which takes a string and replaces spaces with non-breaking html spaces. How do I accomplish this?

code:
@helper NonBreakingSpace(string s)
{
    <text>@s.Replace(" ", "& nbsp;")</text>
}
This won't work because razor will helpfully protect me and output "& ampnbsp;"

Edit: OK, this is hard to talk about on The Internet :v:. Pretend there aren't spaces after the ampersands above.

I think you just need to do @Html.Raw(s.Replace(" ", "&nbsp;")) - possibly without the @ in front of Html

RICHUNCLEPENNYBAGS
Dec 21, 2010

Munkeymon posted:

I think you just need to do @Html.Raw(s.Replace(" ", "&nbsp;")) - possibly without the @ in front of Html

@(new MvcHtmlString("nbsp;")) will also work.

brap
Aug 23, 2004

Grimey Drawer
Isn't there just a general function to convert a string to html entities where necessary (i.e. use &gt; instead of >)?

Eggnogium
Jun 1, 2010

Never give an inch! Hnnnghhhhhh!

fleshweasel posted:

Isn't there just a general function to convert a string to html entities where necessary (i.e. use &gt; instead of >)?

http://msdn.microsoft.com/en-us/library/73z22y6h.aspx

wwb
Aug 17, 2004

It is 2014. Please leave
code:
&nbsp;
in the last century.

Newf
Feb 14, 2006
I appreciate hacky sack on a much deeper level than you.

wwb posted:

It is 2014. Please leave
code:
&nbsp;
in the last century.

In favor of the css white-space: nowrap? What's the advantage?

epswing
Nov 4, 2003

Soiled Meat

wwb posted:

It is 2014. Please leave
code:
&nbsp;
in the last century.

I'm displaying a DateTime in a table and when the width gets too small I still want
pre:
Jul 11 6:18 AM
Jul 11 7:48 AM
Jul 11 8:15 AM
instead of
pre:
Jul 
11 6:18
AM
Jul 
11 7:48
AM
Jul 
11 8:15
AM
What do you suggest?

Che Delilas
Nov 23, 2009
FREE TIBET WEED
Web security-related question here. I'm coding up a set of pages that will let administrators manage user accounts for a web site that uses ASP.NET Identity. Is it dangerous at all to return full entries from the Users table to clients? For example, on one page I'm displaying a list of users and allowing each one to be set to active or inactive.

The full User entity contains fields like PasswordHash and SecurityToken, which I don't need to display to the client. If I return View(context.Users.ToList()); then those fields will be transmitted to the client even if the view doesn't make use of them, right? Can someone who knows how do anything evil with those values?

I know about one-way encryption and password hashing, so I don't need the 101 version, but security is such a complex topic and I've never taken the time to really dive into it, so I'm curious. Oh, and I know how to render the issue moot by using a ViewModel containing only the values the View cares about; it really is just an academic question at the moment.

Quebec Bagnet
Apr 28, 2009

mess with the honk
you get the bonk
Lipstick Apathy

Che Delilas posted:

The full User entity contains fields like PasswordHash and SecurityToken, which I don't need to display to the client. If I return View(context.Users.ToList()); then those fields will be transmitted to the client even if the view doesn't make use of them, right? Can someone who knows how do anything evil with those values?

I know about one-way encryption and password hashing, so I don't need the 101 version, but security is such a complex topic and I've never taken the time to really dive into it, so I'm curious. Oh, and I know how to render the issue moot by using a ViewModel containing only the values the View cares about; it really is just an academic question at the moment.

No, the values only go as far as the view rendering code, and go away once that finishes. If you never use them in the view, they will never go to the client.

Che Delilas
Nov 23, 2009
FREE TIBET WEED

chmods please posted:

No, the values only go as far as the view rendering code, and go away once that finishes. If you never use them in the view, they will never go to the client.

Oh, the View (the .cshtml file in my case) isn't what the client sees, is it? It describes how to generate the final HTML, which is then sent to the client. That's never really clicked in my head until now.

Thanks, that's a big help, especially when it comes to getting into the right mindset for web dev.

evilfunkyogi
Jun 27, 2005
:effort:

epalm posted:

I'm displaying a DateTime in a table and when the width gets too small I still want
pre:
Jul 11 6:18 AM
Jul 11 7:48 AM
Jul 11 8:15 AM
instead of
pre:
Jul 
11 6:18
AM
Jul 
11 7:48
AM
Jul 
11 8:15
AM
What do you suggest?

white-space: nowrap?

Funking Giblet
Jun 28, 2004

Jiglightful!

Che Delilas posted:

Oh, the View (the .cshtml file in my case) isn't what the client sees, is it? It describes how to generate the final HTML, which is then sent to the client. That's never really clicked in my head until now.

Thanks, that's a big help, especially when it comes to getting into the right mindset for web dev.

I would still use an object for the view that contains only what you want, as you may run into trouble later if you say, need to post values back and are trying to save the user back to the database, or a junior decides to output a property by accident.

Look at AutoMapper which will help you create viewmodels from models using conventions and some configuration, which are just representations of your data which is just used for the view.

Che Delilas
Nov 23, 2009
FREE TIBET WEED

Funking Giblet posted:

I would still use an object for the view that contains only what you want, as you may run into trouble later if you say, need to post values back and are trying to save the user back to the database, or a junior decides to output a property by accident.

Look at AutoMapper which will help you create viewmodels from models using conventions and some configuration, which are just representations of your data which is just used for the view.

I'll keep AutoMapper in mind - this project is pretty simple, so I'm happy just manually creating all my viewmodels, but I've seen it mentioned before a number of times as a real energy saver.

Destroyenator
Dec 27, 2004

Don't ask me lady, I live in beer

Che Delilas posted:

I'll keep AutoMapper in mind - this project is pretty simple, so I'm happy just manually creating all my viewmodels, but I've seen it mentioned before a number of times as a real energy saver.
I'm not convinced by it. I've seen it in projects before and you either don't get any information when you rename/delete fields on either side, or you use it's validator which involves writing out either all the mappings or all the differences for each pair of classes at which point why not just write the mapping yourself? Unless I'm missing something major I don't see the value there?

Funking Giblet
Jun 28, 2004

Jiglightful!

Destroyenator posted:

I'm not convinced by it. I've seen it in projects before and you either don't get any information when you rename/delete fields on either side, or you use it's validator which involves writing out either all the mappings or all the differences for each pair of classes at which point why not just write the mapping yourself? Unless I'm missing something major I don't see the value there?

I think you're missing something major! You can validate the configuration at runtime which will find unmapped fields, or write a unit test to do as much. Not to mention injectable value and type resolvers which can be reused across types.

Funking Giblet fucked around with this message at 11:03 on Nov 27, 2014

Ochowie
Nov 9, 2007

This is from a few pages back, but what is the difference between VS Community and Pro? On the Website it says it's a version of the Pro products optimized for small teams but I'm not sure what that means. Are there features that are left out or are they realigned to support smaller teams?

Forgall
Oct 16, 2012

by Azathoth

Ochowie posted:

This is from a few pages back, but what is the difference between VS Community and Pro? On the Website it says it's a version of the Pro products optimized for small teams but I'm not sure what that means. Are there features that are left out or are they realigned to support smaller teams?
Not sure about features, but if your company makes over 1 million in profits or you have VS installed on over 250 (or 150? can't remember) machines you need to buy Pro license. Also maybe I'm missing something, but I don't see code coverage in Community.

EssOEss
Oct 23, 2006
128-bit approved

Forgall posted:

if your company makes over 1 million in profits or you have VS installed on over 250 (or 150? can't remember) machines you need to buy Pro license.

That's if you have over $1M revenue or over 250 computers total, regardless of Visual Studio installation status on those computers.

A company may have Visual Studio Community Edition installed on up to 5 computers. Any beyond that require a Pro license unless they are used to develop open source software or for educational purposes (in which case the count is not limited).

LiteraryDouble
Nov 28, 2014

Hello friends.
Just switched jobs from Java to .NET.

I keep getting assigned to creating Windows Services that do tasks on a scheduled basis.
(e.g. sync database to external source every 5 minutes, do business logic stuff every 7 days, etc).

Any time I use anything related to System.Threading.Timer, or even just massive Thread.Sleeps in prototypes, I get my poo poo garbage collected (I think?) when running in a service, but works fine in Console app prototypes.

As in, logs will show it triggers and runs for one or two goes, and then it always dies, though the service itself persists.

Any idea what the hell I'm doing wrong?

I can throw a sample on github.

LiteraryDouble
Nov 28, 2014

Hello friends.
(whoops double post)

epswing
Nov 4, 2003

Soiled Meat
Sounds like you'd want to look at NCron and NLog.

There are others that do essentially the same thing, but those have worked well for me when I need to (A) do stuff at specified intervals and (B) keep a log of what happened when.

biznatchio
Mar 31, 2001


Buglord

ljw1004 posted:



Note: although the ?. operator is built into C#6 and VB14, the warning squiggle and codefix in this video are not built in. I wrote them myself via a simple "analyzer" - I put the source code here on github. For me the single most important feature of VS2015 is that you can write your own refactorings, analyzers and code-fixes.

Saw this from a few days back --- is this a safe refactoring? Does the ?. operator take a local copy to be consistent across the null check and the method invocation?

Adbot
ADBOT LOVES YOU

EssOEss
Oct 23, 2006
128-bit approved

LiteraryDouble posted:

Just switched jobs from Java to .NET.

I keep getting assigned to creating Windows Services that do tasks on a scheduled basis.
(e.g. sync database to external source every 5 minutes, do business logic stuff every 7 days, etc).

Any time I use anything related to System.Threading.Timer, or even just massive Thread.Sleeps in prototypes, I get my poo poo garbage collected (I think?) when running in a service, but works fine in Console app prototypes.

As in, logs will show it triggers and runs for one or two goes, and then it always dies, though the service itself persists.

Any idea what the hell I'm doing wrong?

I can throw a sample on github.

Yes, a sample might help. Sounds like a defect in your code somewhere but it is hard to diagnose without, you know, seeing the code. Possible causes are numerous, from an unexpected exception ruining your day to a misunderstanding of the timer system and/or what being garbage collected means.

Here is some real simple code I have used to run jobs in services:

code:
	/// <remarks>
	/// NB! Must be disposed of manually or you leak the job.
	/// This class is NOT thread-safe!
	/// </remarks>
	internal abstract class Job : IDisposable
	{
		/// <summary>
		/// If the job stops running without a good reason, the run thread waits this long before starting it again
		/// (unless the job gets stopped earlier). Internal for testing purposes only - do not touch!
		/// </summary>
		internal static TimeSpan RestartDelay = TimeSpan.FromMinutes(1);

		/// <summary>
		/// Starts the job! The job will be automatically restarted on exception, until RequestStop() is called.
		/// </summary>
		public void Start()
		{
			if (_isRunning)
				return;

			// Just in case we still have some lingering thread hoooked up.
			WaitForStop();

			_isRunning = true;

			_cancellationTokenSource = new CancellationTokenSource();

			_runThread = new Thread(RunThread);
			_runThread.Name = GetType().Name;
			_runThread.IsBackground = true;
			_runThread.Start(_cancellationTokenSource.Token);
		}

		/// <summary>
		/// Notifies the job background process that it is to stop but does not wait for it to actually finish processing.
		/// </summary>
		public void RequestStop()
		{
			if (!_isRunning)
				return;

			_isRunning = false;

			_cancellationTokenSource.Cancel();
		}

		/// <summary>
		/// Waits for the job to stop. You must have called Stop() first.
		/// </summary>
		public void WaitForStop()
		{
			if (_isRunning)
				throw new InvalidOperationException("The job is running - you cannot wait for it to stop before asking it to stop!");

			if (_runThread == null)
				return;

			// You better have called Stop() before or you are in trouble!

			_runThread.Join();
		}

		public void Dispose()
		{
			RequestStop();
			WaitForStop();
		}

		protected Job(LogSource log)
		{
			Argument.ValidateIsNotNull(log, "log");

			_log = log;
		}

		/// <summary>
		/// Does the actual "work". If this function returns or throws an exception, it is simply started again.
		/// The cancellation token signals that the job was requested to stop while in the middle of processing.
		/// </summary>
		/// <remarks>
		/// Implementations are strongly recommended to check for cancel at the end of a cycle, as this greatly simplfies
		/// the patterns needed to create "run the job once" style automated tests (because you can just cancel right after start).
		/// </remarks>
		protected abstract void Run(CancellationToken cancel);

		/// <summary>
		/// The log source dedicated to this job. Use for whatever.
		/// </summary>
		protected readonly LogSource _log;

		private CancellationTokenSource _cancellationTokenSource;
		private bool _isRunning;
		private Thread _runThread;

		private void RunThread(object cancelToken)
		{
			var cancel = (CancellationToken)cancelToken;

			while (true)
			{
				try
				{
					_log.Debug("Job cycle starting.");

					Run(cancel);

					if (cancel.IsCancellationRequested)
					{
						_log.Debug("Job cycle ended. This is normal because the job is stopping.");
						return;
					}

					_log.Warning("Job cycle ended without cause even though it was not asked to stop. Scheduling job for restart.");
				}
				catch (Exception ex)
				{
					_log.Warning("Job cycle ended with exception. Scheduling job for restart.");

					ErrorReport.Send(ex);
				}

				// We deliberately check this only at the end of each cycle, to allow for the "cancel right after start" pattern.
				// Wait a bit before restarting, just so we do not cause overload in case we fall into a pit of failure.
				if (cancel.WaitHandle.WaitOne(RestartDelay))
					return;
			}
		}
	}
Run() is meant to never return unless the job is cancelled.

code:
		protected override void Run(CancellationToken cancel)
		{
			while (true)
			{
				// Do some work

				_log.Debug("Sleeping for {0:F0} minutes.", sleepSpan.TotalMinutes);

				if (cancel.WaitHandle.WaitOne(sleepSpan))
					break;
			}

			_log.Debug("Stopping as requested.");
		}

EssOEss fucked around with this message at 23:38 on Nov 28, 2014

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