Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • World
  • Users
  • Groups
Skins
  • Light
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Code Project
  1. Home
  2. General Programming
  3. C#
  4. Threading inside WCF

Threading inside WCF

Scheduled Pinned Locked Moved C#
helpcsharpdatabasewcfdebugging
20 Posts 6 Posters 4 Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • A AmitGajjar

    Hi, This is because environment is multithreaded. You need to add one more statement to let first thread complete and process on another. This is because you need your process in sequence. Use

    t.Join()

    to let first thread complete before second starts in your GetData function.

    Thanks -Amit Gajjar (MinterProject)

    N Offline
    N Offline
    Nand32
    wrote on last edited by
    #4

    well, I don't think that's the reason because the reason for using threads here is _not_ to let it wait for the next call. Otherwise I would have made a simple for loop without threads right? The loop is running too fast, before the thread function could pick up the variable's value. If I put a Thread.Sleep(100) after each call, the sequence comes in the right order. Just as a POC , try this on a C# console Application, it would put them in right order. As simple as that! But I sense WCF requires something else, to persist the value of the passed variable. But No search helps.

    A 1 Reply Last reply
    0
    • M Manfred Rudolf Bihy

      I'm quite reluctant to believe you're getting any kind of result at all as your code wouldn't even compile:

      [OperationContract]
      public string GetData(int value)
      {
      for (int i = 0; i < 4; i++)
      {
      Thread t = new Thread(() => simpleThread(i));
      t.Start();
      }
      // Since the signature of this method is String GetData(int)
      // This will never pass the compilation process as the method
      // needs to return a String
      }

      Compilation would fail because of the missing return statement. Regards,

      — Manfred

      "I had the right to remain silent, but I didn't have the ability!"

      Ron White, Comedian

      N Offline
      N Offline
      Nand32
      wrote on last edited by
      #5

      Updated it.

      M 1 Reply Last reply
      0
      • N Nand32

        I have a very simple WCF service, : [service contract] public class Service1 : IService1 { List m_list = new List(); public Service1() { for (int i = 0; i < 10; i++) { m_list.Add(i); } } [OperationContract] public string GetData(int value) { for (int i = 0; i < 4; i++) { Thread t = new Thread(() => simpleThread(i)); t.Start(); } return "text"; // :| } void simpleThread(int i_in) { Trace.WriteLine(m_list[i_in].ToString()); } } The code stores 0,1,2,3 as values inside m_list. So m_list[0] is 0, [1] is 1 .. [3] is 3. And when we print it through "SimpleThread(int i)" Thread function, In the log it's supposed to be 0,1,2,3 but it's always like 2,2,3 or something weird. And the index passed in itself is wrong. It never passes 0,1. And sometimes it prints... 4 : 4 4 : 4 4 : 4 4 : 4 And the problem is random. I'm missing something very fundamental with threading on WCF. Any help please? I would like to get it : 0 : 0 1 : 1 2 : 2 3 : 3

        S Offline
        S Offline
        Steve44
        wrote on last edited by
        #6

        The problem is the lambda expression, it references the variable i of the outer method at the time of the thread execution, and that is likely after all threads are created. This is not like a passed parameter that gets copied at the time of the thread creation. Try creating a thread that takes a parameter and pass the i there, this should resolve the issue.

        N 1 Reply Last reply
        0
        • N Nand32

          Updated it.

          M Offline
          M Offline
          Manfred Rudolf Bihy
          wrote on last edited by
          #7

          While rummaging around in my brain a bit I suddenly had a case of deja vu. The problem lies here in closures, lambda expressions and their interaction with threading. I'm not sure if I found the post I read a couple of years ago, but here it goes: Lambda expressions, captured variables and threading[^]. Especially enlightening is answer 2. Thus please try to rewrite your code in this manner:

          [OperationContract]
          public string GetData(int value)
          {
          for (int i = 0; i < 4; i++)
          {
          Thread t = new Thread(() => {
          int j = i; // not quite sure if this is needed,
          // but try leaving it out and see what happens.
          simpleThread(j); // if you leave out the above statement change j to i on this line
          });
          t.Start();
          }
          return ""; // An empty string is also a string ;)
          }

          Regards,

          — Manfred

          "I had the right to remain silent, but I didn't have the ability!"

          Ron White, Comedian

          N 1 Reply Last reply
          0
          • N Nand32

            well, I don't think that's the reason because the reason for using threads here is _not_ to let it wait for the next call. Otherwise I would have made a simple for loop without threads right? The loop is running too fast, before the thread function could pick up the variable's value. If I put a Thread.Sleep(100) after each call, the sequence comes in the right order. Just as a POC , try this on a C# console Application, it would put them in right order. As simple as that! But I sense WCF requires something else, to persist the value of the passed variable. But No search helps.

            A Offline
            A Offline
            AmitGajjar
            wrote on last edited by
            #8

            There is difference between normal loop and using thread. if you are using normal loop your application will hang till your loop completed. while in thread other thread will run and your application will not hang.

            Thanks -Amit Gajjar (MinterProject)

            N 1 Reply Last reply
            0
            • M Manfred Rudolf Bihy

              While rummaging around in my brain a bit I suddenly had a case of deja vu. The problem lies here in closures, lambda expressions and their interaction with threading. I'm not sure if I found the post I read a couple of years ago, but here it goes: Lambda expressions, captured variables and threading[^]. Especially enlightening is answer 2. Thus please try to rewrite your code in this manner:

              [OperationContract]
              public string GetData(int value)
              {
              for (int i = 0; i < 4; i++)
              {
              Thread t = new Thread(() => {
              int j = i; // not quite sure if this is needed,
              // but try leaving it out and see what happens.
              simpleThread(j); // if you leave out the above statement change j to i on this line
              });
              t.Start();
              }
              return ""; // An empty string is also a string ;)
              }

              Regards,

              — Manfred

              "I had the right to remain silent, but I didn't have the ability!"

              Ron White, Comedian

              N Offline
              N Offline
              Nand32
              wrote on last edited by
              #9

              Thanks for your efforts, but it still didn't work Mr.Manfred This produced a debug out like:

              3 : 3
              3 : 3
              3 : 3
              4 : 4

              I tried Parameterized Thread start:

                ParameterizedThreadStart pt = new System.Threading.ParameterizedThreadStart(simpleThread);
                          Thread t = new System.Threading.Thread(pt);
                          t.Start(i);
              

              It produces:

              0 : 0
              2 : 2
              3 : 3
              1 : 1

              It covered all the indexes, but still it's not in the right order. May be we can't expect this in the right order? as they are "Threads!"?

              M N 2 Replies Last reply
              0
              • S Steve44

                The problem is the lambda expression, it references the variable i of the outer method at the time of the thread execution, and that is likely after all threads are created. This is not like a passed parameter that gets copied at the time of the thread creation. Try creating a thread that takes a parameter and pass the i there, this should resolve the issue.

                N Offline
                N Offline
                Nand32
                wrote on last edited by
                #10

                Please check this[^] Is that fine?

                1 Reply Last reply
                0
                • N Nand32

                  Thanks for your efforts, but it still didn't work Mr.Manfred This produced a debug out like:

                  3 : 3
                  3 : 3
                  3 : 3
                  4 : 4

                  I tried Parameterized Thread start:

                    ParameterizedThreadStart pt = new System.Threading.ParameterizedThreadStart(simpleThread);
                              Thread t = new System.Threading.Thread(pt);
                              t.Start(i);
                  

                  It produces:

                  0 : 0
                  2 : 2
                  3 : 3
                  1 : 1

                  It covered all the indexes, but still it's not in the right order. May be we can't expect this in the right order? as they are "Threads!"?

                  M Offline
                  M Offline
                  Manfred Rudolf Bihy
                  wrote on last edited by
                  #11

                  VKAnanth wrote:

                  May be we can't expect this in the right order? as they are "Threads!"?

                  You hit it spot on. Threads are scheduled by the system when to run and for how long. So what you are observing now is the expected behaviour, eventhough there might be circumstances where the order would be what you presumed first :). Did you also try the third alternative from the SO post I referenced in my solution attempt? Regards,

                  — Manfred

                  PS: Skip the Mr. stuff, we're all peers here on CP. ;)

                  "I had the right to remain silent, but I didn't have the ability!"

                  Ron White, Comedian

                  N 1 Reply Last reply
                  0
                  • A AmitGajjar

                    There is difference between normal loop and using thread. if you are using normal loop your application will hang till your loop completed. while in thread other thread will run and your application will not hang.

                    Thanks -Amit Gajjar (MinterProject)

                    N Offline
                    N Offline
                    Nand32
                    wrote on last edited by
                    #12

                    Yup, but still Thread.Join wouldn't let the control go past the function scope. It makes it wait there until the threads complete their execution. In short, it "BLOCKS" too.

                    A 1 Reply Last reply
                    0
                    • M Manfred Rudolf Bihy

                      VKAnanth wrote:

                      May be we can't expect this in the right order? as they are "Threads!"?

                      You hit it spot on. Threads are scheduled by the system when to run and for how long. So what you are observing now is the expected behaviour, eventhough there might be circumstances where the order would be what you presumed first :). Did you also try the third alternative from the SO post I referenced in my solution attempt? Regards,

                      — Manfred

                      PS: Skip the Mr. stuff, we're all peers here on CP. ;)

                      "I had the right to remain silent, but I didn't have the ability!"

                      Ron White, Comedian

                      N Offline
                      N Offline
                      Nand32
                      wrote on last edited by
                      #13

                      I'm just letting the monkey go off my head at the moment as the code works with the ParametereizedThread start. Packing the code and sending it to my mates. Once done, will come back to explore the method that you pointed out. cheers! Mr. Manfred :java: :)

                      S 1 Reply Last reply
                      0
                      • N Nand32

                        Yup, but still Thread.Join wouldn't let the control go past the function scope. It makes it wait there until the threads complete their execution. In short, it "BLOCKS" too.

                        A Offline
                        A Offline
                        AmitGajjar
                        wrote on last edited by
                        #14

                        Yes ofcourse it will block that thread execution. but it will not block others. let me know if that works for you. As you have mention earlier you are using thread.sleep but why you need it ?

                        Thanks -Amit Gajjar (MinterProject)

                        N 1 Reply Last reply
                        0
                        • A AmitGajjar

                          Yes ofcourse it will block that thread execution. but it will not block others. let me know if that works for you. As you have mention earlier you are using thread.sleep but why you need it ?

                          Thanks -Amit Gajjar (MinterProject)

                          N Offline
                          N Offline
                          Nand32
                          wrote on last edited by
                          #15

                          I removed it, I just tried "Sleep"ing to check if it's a Sync issue. Sleep helped to print the index in order, but misses the whole point of using threads. - need to run fast. And Sleep is just for debugging. never a solution, unless the BugFix-Priority-Column says "Fix Right NoW". ;)

                          A 1 Reply Last reply
                          0
                          • N Nand32

                            I removed it, I just tried "Sleep"ing to check if it's a Sync issue. Sleep helped to print the index in order, but misses the whole point of using threads. - need to run fast. And Sleep is just for debugging. never a solution, unless the BugFix-Priority-Column says "Fix Right NoW". ;)

                            A Offline
                            A Offline
                            AmitGajjar
                            wrote on last edited by
                            #16

                            For your knowledge, Thread is used when you do not want any task in sequence. if you need some task to be in sequence you need to use single threaded function. if you are doing thread.join() it will not degrade performance of your application, although it will impact on your current thread. at that time other thread will keep executing. First you need to decide if your current process is not meant to execute in sequence then you can defiantly use thread. hope this makes sense.

                            Thanks -Amit Gajjar (MinterProject)

                            1 Reply Last reply
                            0
                            • N Nand32

                              I'm just letting the monkey go off my head at the moment as the code works with the ParametereizedThread start. Packing the code and sending it to my mates. Once done, will come back to explore the method that you pointed out. cheers! Mr. Manfred :java: :)

                              S Offline
                              S Offline
                              Steve44
                              wrote on last edited by
                              #17

                              Threading is not deterministic in the order of execution unless you add constructs to synchronize your threads, e.g. Thread 2 waits for completion of Thread 1 before it starts, Thread 3 waits for completion of Thread 2 before it starts, etc. But that would defeat the purpose of threading, if you create threads to allow parallel execution, but then you serialize all of their execution. (On a multi-core machine, they can even be scheduled to execute physically at the same time, which opens up a can of even more indeterministic behavior ;) )

                              1 Reply Last reply
                              0
                              • N Nand32

                                Thanks for your efforts, but it still didn't work Mr.Manfred This produced a debug out like:

                                3 : 3
                                3 : 3
                                3 : 3
                                4 : 4

                                I tried Parameterized Thread start:

                                  ParameterizedThreadStart pt = new System.Threading.ParameterizedThreadStart(simpleThread);
                                            Thread t = new System.Threading.Thread(pt);
                                            t.Start(i);
                                

                                It produces:

                                0 : 0
                                2 : 2
                                3 : 3
                                1 : 1

                                It covered all the indexes, but still it's not in the right order. May be we can't expect this in the right order? as they are "Threads!"?

                                N Offline
                                N Offline
                                Nicholas Marty
                                wrote on last edited by
                                #18

                                If you don't want to execute this sequence on the current thread but still in the same order you could try to just execute the whole loop in another thread. Change:

                                for (int i = 0; i < 4; i++)
                                {
                                Thread t = new Thread(() => simpleThread(i));
                                t.Start();
                                }

                                to:

                                Thread t = new Thread(() => {
                                for (int i = 0; i < 4; i++) {
                                simpleThread(i);
                                }
                                });
                                t.Start();

                                This would process all items in the right order while still running in another (not blocking) thread.

                                1 Reply Last reply
                                0
                                • N Nand32

                                  I have a very simple WCF service, : [service contract] public class Service1 : IService1 { List m_list = new List(); public Service1() { for (int i = 0; i < 10; i++) { m_list.Add(i); } } [OperationContract] public string GetData(int value) { for (int i = 0; i < 4; i++) { Thread t = new Thread(() => simpleThread(i)); t.Start(); } return "text"; // :| } void simpleThread(int i_in) { Trace.WriteLine(m_list[i_in].ToString()); } } The code stores 0,1,2,3 as values inside m_list. So m_list[0] is 0, [1] is 1 .. [3] is 3. And when we print it through "SimpleThread(int i)" Thread function, In the log it's supposed to be 0,1,2,3 but it's always like 2,2,3 or something weird. And the index passed in itself is wrong. It never passes 0,1. And sometimes it prints... 4 : 4 4 : 4 4 : 4 4 : 4 And the problem is random. I'm missing something very fundamental with threading on WCF. Any help please? I would like to get it : 0 : 0 1 : 1 2 : 2 3 : 3

                                  J Offline
                                  J Offline
                                  jschell
                                  wrote on last edited by
                                  #19

                                  VKAnanth wrote:

                                  And the problem is random

                                  Ast stated elsewhere... No the problem is that you are using threads and you think that there should be an order. It is simple - stopping thinking that. There is no order. It doesn't matter how you create them nor execute them - there still is no order. If you want an order then you must assert that order yourself into the code. HOW you do that depends on what you actually want to acheive. It could be as simple as just ordering the final set after processing of all the threads completes. Or providing a bucket into which each thread puts its result.

                                  S 1 Reply Last reply
                                  0
                                  • J jschell

                                    VKAnanth wrote:

                                    And the problem is random

                                    Ast stated elsewhere... No the problem is that you are using threads and you think that there should be an order. It is simple - stopping thinking that. There is no order. It doesn't matter how you create them nor execute them - there still is no order. If you want an order then you must assert that order yourself into the code. HOW you do that depends on what you actually want to acheive. It could be as simple as just ordering the final set after processing of all the threads completes. Or providing a bucket into which each thread puts its result.

                                    S Offline
                                    S Offline
                                    Steve44
                                    wrote on last edited by
                                    #20

                                    Sometimes the execution order does not matter, but the publishing of the result (e.g. if your processing takes significant time before results are available). In this case you should spinup the threads and let them execute in any order as they will, but when the results are available wait for the completion of the "previous" thread and then publish your results. Using a pattern like this would allow to use the parallel execution of the long processing and still have the serialized behavior at time of the publishing of the results.

                                    1 Reply Last reply
                                    0
                                    Reply
                                    • Reply as topic
                                    Log in to reply
                                    • Oldest to Newest
                                    • Newest to Oldest
                                    • Most Votes


                                    • Login

                                    • Don't have an account? Register

                                    • Login or register to search.
                                    • First post
                                      Last post
                                    0
                                    • Categories
                                    • Recent
                                    • Tags
                                    • Popular
                                    • World
                                    • Users
                                    • Groups