0

I am trying to write a small threaded application and wanted to know how I could implement the below IEnum as thread/threaded? Absolute beginner to threading, not even sure the below method can be threaded. Would appreciate a little walk through.

    static void Main(string[] args)
    {
        IEnumerable<string> e = Enumerable.Range(1, 100).Select(
            n =>   
              (n % 15 == 0) ? "Fizzbuzz" :
                  (n % 3 == 0) ? "Fizz" :
                      (n % 5 == 0) ? "buzz" :
                          n.ToString())
                           .ToList();
        WriteFile(e);
    }
    private static ReaderWriterLockSlim _readWriteLock = new ReaderWriterLockSlim();
    private static void WriteFile(IEnumerable<string> text)
    {
        _readWriteLock.EnterWriteLock();
        string path = @"C:\Users\Desktop\Test.txt";
        try
        { 
            using (StreamWriter stream = File.AppendText(path))
            {
                    foreach (var item in text)
                    {
                        stream.WriteLine(item); 
                    }
                stream.Close();
            }
        }
        catch (Exception e)
        {
            throw (e);
        }
        finally
        {
                    // Release lock
                    _readWriteLock.ExitWriteLock();
        }
    }
G Gr
  • 6,030
  • 20
  • 91
  • 184
  • 1
    First of all, you're not using threads so you don't need to worry about thread safety. Second, you're only reading from the collection and never writing to it after it's defined so there's no worry of modification from other threads anyway... – Justin Niessner May 05 '15 at 02:39
  • Ah sorry I should redfine my question, how could I make the IEnum threaded? Never attempted a threaded application before and just wondered how it was done, using the example above. – G Gr May 05 '15 at 02:45
  • Please don't ever code `catch (Exception e) { throw (e); }`. It's a terrible practice and will just provide an environment where bugs can breed. – Enigmativity May 05 '15 at 02:47
  • What you expect you enumerable to do differently when "make the IEnum threaded"? – Alexei Levenkov May 05 '15 at 02:49
  • @Enigmativity That is for stackoverflow purposes. There is no need to show exception code on here if its not part of the question. (Keeps the code short and concise for readability) – G Gr May 05 '15 at 02:49
  • @GarrithGraham - Then remove the exception code entirely. :-) – Enigmativity May 05 '15 at 02:51
  • Yes but then another SO Ninja will come along and say... please use exception handling in your code. You can never win! – G Gr May 05 '15 at 02:55
  • 1
    There is similar question http://stackoverflow.com/questions/5061761/is-it-possible-to-await-yield-return-dosomethingasync (also it talks about `async`, but it may be of interest at least). – Alexei Levenkov May 05 '15 at 02:56

1 Answers1

2

Does this work for you?

static void Main(string[] args)
{
    IEnumerable<string> e =
        Enumerable
            .Range(1, 100)
            .AsParallel()
            .Select(
                n =>   
                    (n % 15 == 0) ? "Fizzbuzz" :
                    (n % 3 == 0) ? "Fizz" :
                    (n % 5 == 0) ? "buzz" :
                    n.ToString())
            .ToList();
    WriteFile(e);
}

private static ReaderWriterLockSlim _readWriteLock = new ReaderWriterLockSlim();
private static void WriteFile(IEnumerable<string> text)
{
    try
    {
        _readWriteLock.EnterWriteLock();
        File.AppendAllLines(@"C:\Users\Desktop\Test.txt", text);
    }
    finally
    {
        _readWriteLock.ExitWriteLock();
    }
}

Note the .AsParallel() call.

But, if you do do it this way then there is no need for the locks.

Enigmativity
  • 113,464
  • 11
  • 89
  • 172
  • If the range was much larger, would this method be any faster? – G Gr May 05 '15 at 02:58
  • @GarrithGraham - No. Your computation is exceedingly fast so threading is very unlikely to speed this up. If you were computing something that was time consuming then threading would be very useful. – Enigmativity May 05 '15 at 03:00
  • Thank you, it makes it really hard to know when and where to use threading. As I mention in the post, complete beginner just a passing interest. – G Gr May 05 '15 at 03:02
  • @GarrithGraham - You should almost always avoid threading. It very often makes your code difficult to understand, debug, and manage - and it often isn't as fast as you think it will be. – Enigmativity May 05 '15 at 03:04
  • @GarrithGraham - You are far better off using asynchrony rather than explicit multithreading. Using `async`/`await`, or tasks or the reactive framework is a far better idea. – Enigmativity May 05 '15 at 03:05
  • Hmm AsParallel also doesnt output the above in the correct sequence? Another byproduct? – G Gr May 05 '15 at 03:06
  • @GarrithGraham - There's the rub with parallel processing - now you have to do a sort at the end and that'll wipe away the advantage of running the computation in parallel. Hence the advantage is only there for time consuming computations. – Enigmativity May 05 '15 at 03:11
  • Appending AsParallel to the end of the linq statement after the ToList seems to have solved it but... that could just be luck on the times I have ran the program or isnt applied in the correct manner. Sort would take away the advantage. Can I ask if you have done normal application development how many times you have used multithreading/parallel processing? – G Gr May 05 '15 at 03:14
  • @GarrithGraham - Adding `.AsParallel()` after the `.ToList()` does nothing - your computation is completed synchronously when the `.ToList()` is called. `.AsParallel()` doesn't perform any actual work so it is instant. This proves that your computation is **quicker** without threading. – Enigmativity May 05 '15 at 03:19
  • @GarrithGraham - I have done and do application development. I rarely directly use threads. Instead I prefer using Microsoft's Reactive Framework (Nuget "Rx-Main") when doing any threading/asynchronous work. – Enigmativity May 05 '15 at 03:21