0

How can I run the code below in LinqPad as C# Program Thank you...

class ThreadTest
{
    static void Main()
    {
        Thread t = new Thread (WriteY);          // Kick off a new thread
        t.Start();                               // running WriteY()

        // Simultaneously, do something on the main thread.
        for (int i = 0; i < 1000; i++) Console.Write ("x");
    }

    static void WriteY()
    {
        for (int i = 0; i < 1000; i++) Console.Write ("y");
    }
}

Result Expected

xxxxxxxxxxxxxxxxyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx ...

So far I came up with

static void Main()
{
    Thread t = new Thread (ThreadTest.WriteY);          // Kick off a new thread
    t.Start();                                          // running WriteY()

    // Simultaneously, do something on the main thread.
    for (int i = 0; i < 1000; i++) Console.Write ("x");
}

class ThreadTest
{
    public static void WriteY()
    {
        for (int i = 0; i < 1000; i++) Console.Write ("y");
    }
}

Actual Result

xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx...yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy...

As seen on Result Expected it should be mixed X and Y.
Unfortunately Actual Result is 1000 times X and 1000 times Y

UPDATE

This sample - along with all the others in the concurrency chapters of C# 5 in a Nutshell are downloadable as a LINQPad sample library. Go to LINQPad's samples TreeView and click 'Download/Import more samples' and choose the first listing. – Joe Albahari

cilerler
  • 9,010
  • 10
  • 56
  • 91
  • I think linqpad is the reason for this, I tried it myself the other day and got the same results. I ended up using a Console Application. I wonder if there is any magic thread synchronising happening under the covers. – DaveShaw Jan 30 '14 at 16:21
  • I believe you will get different results regardless. Maybe try locking or sleeping them? – Jon Douglas Jan 30 '14 at 16:29
  • @JonDouglas unfortunately getting different result are not the problem here. result is keep coming as X's are first Y's are second. It should be mixed – cilerler Jan 30 '14 at 16:31
  • 1
    Even testing your program, though it's not mixed xyxyxyxyxyx, I'm still getting many mixed results (xxxxxxxxxxxxyyyyyyyyyyyyyxxxxxxxxxxxxxy) - Note this is done through LINQPad – Jon Douglas Jan 30 '14 at 16:45
  • 1
    @cilerler No, it shouldn't, *it can do whatever the heck it wants*. What it is doing is one entirely viable solution to the problem. If you want something else then you need to specify what you want. When you essentially say "I don't care what comes out" you don't get to care what comes out. – Servy Jan 30 '14 at 16:49

2 Answers2

3

Thread switching is by nature non-deterministic. I can run your program multiple times and get varying results.

If you want the switching to be more evident, add some pauses:

static void Main()
{
    Thread t = new Thread (ThreadTest.WriteY);          // Kick off a new thread
    t.Start();                                          // running WriteY()

    // Simultaneously, do something on the main thread.
    for (int i = 0; i < 1000; i++) 
    {
         Console.Write ("x");
         Thread.Sleep(1);
    }
}


class ThreadTest
{
    public static void WriteY()
    {
         for (int i = 0; i < 1000; i++) 
         {
             Console.Write ("y");
             Thread.Sleep(1);
         }
    }
}
D Stanley
  • 149,601
  • 11
  • 178
  • 240
  • unfortunately it is not the answer I'm looking for. I mean it is OK to receive different results (which is expected) but on LinqPad that code returns always X's first Y's second. so 1000*X and 1000*Y so no need to use sleep. – cilerler Jan 30 '14 at 16:34
  • 2
    @cilerler It's not guaranteed to do that, it just happens to be able to write out all of the values just that quickly. Another machine might not be able to do that. The whole point of this answer is that you can have *no expectations* of what will happen. If there is something you specifically want to happen, you need to make it happen. – Servy Jan 30 '14 at 16:46
  • Definitely agree with @Servy here. – Jon Douglas Jan 30 '14 at 16:47
  • I agree with this explanation as well, but was interested to see that `Dump` did seem to behave differently--at least for me, so added an answer saying as much. If any of you can explain why, I'd be happy to read that. – Sven Grosen Jan 30 '14 at 16:50
  • @Servy and JonDouglas as you can see in Ledbutter's answer there is a specific reason I'm experiencing this problem. He is right about Dump() and expected results shows up on screen ;-) So please stop up voting this answer! It is not approaching the problem from the right angle. This is not just a C# question it is related to LinqPad – cilerler Jan 30 '14 at 16:51
  • @cilerler I'm not sure what's different with my setup but I can rerun the program as posted multiple times and get different results (sometimes all x's -> all y's, but sometimes they are mixed. So I don't think it's an inherent problem with LinqPad. If you increase the loop variable to 10,000 do you still get the same results? – D Stanley Jan 30 '14 at 16:59
  • 1
    @cilerler and as far as `Dump` behaving differently it's likely that `Dump` has some overhead that `Console.Write` does not that makes the thread switching more evident (similar to what `Thread.Sleep` does). – D Stanley Jan 30 '14 at 17:01
  • @DStanley you were right, when I set for 10K it did start to change. Thank you for that. All other thank you for the attention but just curiosity, why did you down vote my question? I mean what ground? – cilerler Jan 30 '14 at 17:05
1

I cannot explain why this works, but changing to using Dump() seems to make it behave like the OP wants with the x's and y's "mixed" with every run (although with newlines between every output):

void Main()
{
    Thread t = new Thread (ThreadTest.WriteY);          // Kick off a new thread
    t.Start();                                          // running WriteY()

    // Simultaneously, do something on the main thread.
    for (int i = 0; i < 1000; i++) "x".Dump();
}

class ThreadTest
{
    public static void WriteY()
    {
        for (int i = 0; i < 1000; i++) "y".Dump();
    }
}

From the LinqPAD documentation:

LINQPad's Dump command feeds the output into an XHTML stream which it displays using an embedded web browser (you can see this by right-clicking a query result and choosing 'View Source'. The transformation into XHTML is done entirely using LINQ to XML, as one big LINQ query! The deferred expansion of results works via JavaScript, which means the XHTML is fully prepopulated after a query finishes executing. The lambda window populates using a custom expression tree visitor (simply calling ToString on an expression tree is no good because it puts the entire output on one line).

I also know that LinqPAD overrides the default Console.WriteLine behavior, so perhaps that has something to do with it.

Community
  • 1
  • 1
Sven Grosen
  • 5,616
  • 3
  • 30
  • 52
  • I don't think the Dump() method really has any effect on the output of this particular program. Even testing with a dump extension, it's still non-deterministic results. Still can obtain X^1000 then Y^1000. – Jon Douglas Jan 30 '14 at 16:55
  • @JonDouglas interesting, I was unable to do so even after multiple runs. I agree that this is an unusual request and it isn't something that should be relied upon. – Sven Grosen Jan 30 '14 at 17:03
  • @ledbutter I switched to 10K as suggested and it started to give mixed results as desired. Thank you for the time by the way – cilerler Jan 30 '14 at 17:07