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. WCF UnobservedTaskException

WCF UnobservedTaskException

Scheduled Pinned Locked Moved C#
csharpquestionwpfwcfsysadmin
5 Posts 2 Posters 0 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.
  • B Offline
    B Offline
    Bernhard Hiller
    wrote on last edited by
    #1

    I do not understand why there is an UnobservedTaskException in that code at all... A method in a WCF service is defined as

    \[OperationContract\]
    \[FaultContract(typeof(RemoteException))\]
    Task SetInfraredFocus(string \_clientName, double \_focus);
    

    A WPF application calls out to it via:

    public void SetFocus(double \_focus)
    {
        try
        {
            m\_RemoteManualPsControl.SetInfraredFocus(UtilsEnvironment.TerminalName, \_focus).Wait();
        }
        catch (Exception ex)
        {
            Logger.LogException(Name, ex);
        }
    }
    

    Note the .Wait() and the catch. That in turn calls the WCF client class

    public Task SetInfraredFocus(string \_clientName, double \_focus)
    {
        Task task = new Task(() => RemoteChannelProvider.Call(\_channel => \_channel.SetInfraredFocus(\_clientName, \_focus)));
        task.Start();
        return task;
    } 
    

    True, I ought to add a CallAsync function to our WCF client base class, but that's quite convoluted code there... The server (a singleton service, multi-threaded) has a simple implementation for the sake of demonstration:

    public async Task SetInfraredFocus(string \_clientName, double \_focus)
    {
        try
        {
            await Task.Delay(1);
            throw new Exception("Oh fuck!");
        }
        catch (Exception ex)
        {
            Logger.LogException(Name, ex);
            RemoteException.ThrowFaultExceptionFromException(ex);
        }
    }
    

    And then I get that UnobservedTaskException... Its detail clearly shows where it comes from: it is the RemoteException created from the "Oh fuck!" exception of the server. But why does the "catch" in the function on the top not catch the exception?

    Oh sanctissimi Wilhelmus, Theodorus, et Fredericus!

    Richard DeemingR 1 Reply Last reply
    0
    • B Bernhard Hiller

      I do not understand why there is an UnobservedTaskException in that code at all... A method in a WCF service is defined as

      \[OperationContract\]
      \[FaultContract(typeof(RemoteException))\]
      Task SetInfraredFocus(string \_clientName, double \_focus);
      

      A WPF application calls out to it via:

      public void SetFocus(double \_focus)
      {
          try
          {
              m\_RemoteManualPsControl.SetInfraredFocus(UtilsEnvironment.TerminalName, \_focus).Wait();
          }
          catch (Exception ex)
          {
              Logger.LogException(Name, ex);
          }
      }
      

      Note the .Wait() and the catch. That in turn calls the WCF client class

      public Task SetInfraredFocus(string \_clientName, double \_focus)
      {
          Task task = new Task(() => RemoteChannelProvider.Call(\_channel => \_channel.SetInfraredFocus(\_clientName, \_focus)));
          task.Start();
          return task;
      } 
      

      True, I ought to add a CallAsync function to our WCF client base class, but that's quite convoluted code there... The server (a singleton service, multi-threaded) has a simple implementation for the sake of demonstration:

      public async Task SetInfraredFocus(string \_clientName, double \_focus)
      {
          try
          {
              await Task.Delay(1);
              throw new Exception("Oh fuck!");
          }
          catch (Exception ex)
          {
              Logger.LogException(Name, ex);
              RemoteException.ThrowFaultExceptionFromException(ex);
          }
      }
      

      And then I get that UnobservedTaskException... Its detail clearly shows where it comes from: it is the RemoteException created from the "Oh fuck!" exception of the server. But why does the "catch" in the function on the top not catch the exception?

      Oh sanctissimi Wilhelmus, Theodorus, et Fredericus!

      Richard DeemingR Offline
      Richard DeemingR Offline
      Richard Deeming
      wrote on last edited by
      #2

      Bernhard Hiller wrote:

      Task task = new Task(() => RemoteChannelProvider.Call(_channel => _channel.SetInfraredFocus(_clientName, _focus)));

      That line looks suspicious to me. The RemoteChannelProvider doesn't seem to be a built-in class. What's the signature of the Call method? What I suspect is happening is this:

      1. SetInfraredFocus returns a Task;
      2. Call may or may not discard that task;
      3. Even if it doesn't discard the task, the new Task constructor definitely discards it - none of the overloads accept a Func<Task>;
      4. The task returned from the client therefore doesn't observe the result of the task returned from the server. It could even complete before the server call has finished.

      If the RemoteChannelProvider.Call method returns the Task, then you should be able to fix this by replacing the client code with:

      public Task SetInfraredFocus(string _clientName, double _focus)
      {
      return Task.Run(() => RemoteChannelProvider.Call(_channel => _channel.SetInfraredFocus(_clientName, _focus)));
      }

      Task.Run has overloads which accept a Func<Task>. The task returned from these will not complete until the inner task has completed, and it will propagate any exceptions correctly.


      "These people looked deep within my soul and assigned me a number based on the order in which I joined." - Homer

      "These people looked deep within my soul and assigned me a number based on the order in which I joined" - Homer

      B 1 Reply Last reply
      0
      • Richard DeemingR Richard Deeming

        Bernhard Hiller wrote:

        Task task = new Task(() => RemoteChannelProvider.Call(_channel => _channel.SetInfraredFocus(_clientName, _focus)));

        That line looks suspicious to me. The RemoteChannelProvider doesn't seem to be a built-in class. What's the signature of the Call method? What I suspect is happening is this:

        1. SetInfraredFocus returns a Task;
        2. Call may or may not discard that task;
        3. Even if it doesn't discard the task, the new Task constructor definitely discards it - none of the overloads accept a Func<Task>;
        4. The task returned from the client therefore doesn't observe the result of the task returned from the server. It could even complete before the server call has finished.

        If the RemoteChannelProvider.Call method returns the Task, then you should be able to fix this by replacing the client code with:

        public Task SetInfraredFocus(string _clientName, double _focus)
        {
        return Task.Run(() => RemoteChannelProvider.Call(_channel => _channel.SetInfraredFocus(_clientName, _focus)));
        }

        Task.Run has overloads which accept a Func<Task>. The task returned from these will not complete until the inner task has completed, and it will propagate any exceptions correctly.


        "These people looked deep within my soul and assigned me a number based on the order in which I joined." - Homer

        B Offline
        B Offline
        Bernhard Hiller
        wrote on last edited by
        #3

        That overload does not do the trick either... The "RemoteChannelProvider" is not a built-in class. The signature is:

        public delegate void CallProxyDelegate(T _channel);
        ...
        void Call(CallProxyDelegate _codeBlock, [CallerMemberName] string _functionName = "");

        Some implementation details:

        m_ConfigurationChannelFactory = new ConfigurationDuplexChannelFactory(m_CallbackObject, ConfigurationName, null, config);
        ...
        m_CommunicationChannel = (ICommunicationObject)m_ConfigurationChannelFactory.CreateChannel();
        ...
        _codeBlock((T)m_CommunicationChannel);

        I do not know how that handles a Task.

        Oh sanctissimi Wilhelmus, Theodorus, et Fredericus!

        Richard DeemingR 1 Reply Last reply
        0
        • B Bernhard Hiller

          That overload does not do the trick either... The "RemoteChannelProvider" is not a built-in class. The signature is:

          public delegate void CallProxyDelegate(T _channel);
          ...
          void Call(CallProxyDelegate _codeBlock, [CallerMemberName] string _functionName = "");

          Some implementation details:

          m_ConfigurationChannelFactory = new ConfigurationDuplexChannelFactory(m_CallbackObject, ConfigurationName, null, config);
          ...
          m_CommunicationChannel = (ICommunicationObject)m_ConfigurationChannelFactory.CreateChannel();
          ...
          _codeBlock((T)m_CommunicationChannel);

          I do not know how that handles a Task.

          Oh sanctissimi Wilhelmus, Theodorus, et Fredericus!

          Richard DeemingR Offline
          Richard DeemingR Offline
          Richard Deeming
          wrote on last edited by
          #4

          OK, then it's definitely throwing the Task away. How does the RemoteChannelProvider class cope with server methods which return a value? If it doesn't, you might still be able to hack around it:

          public Task SetInfraredFocus(string _clientName, double _focus)
          {
          return Task.Run(delegate
          {
          Task result = null;
          RemoteChannelProvider.Call(_channel => result = _channel.SetInfraredFocus(_clientName, _focus));
          return result;
          });
          }


          "These people looked deep within my soul and assigned me a number based on the order in which I joined." - Homer

          "These people looked deep within my soul and assigned me a number based on the order in which I joined" - Homer

          B 1 Reply Last reply
          0
          • Richard DeemingR Richard Deeming

            OK, then it's definitely throwing the Task away. How does the RemoteChannelProvider class cope with server methods which return a value? If it doesn't, you might still be able to hack around it:

            public Task SetInfraredFocus(string _clientName, double _focus)
            {
            return Task.Run(delegate
            {
            Task result = null;
            RemoteChannelProvider.Call(_channel => result = _channel.SetInfraredFocus(_clientName, _focus));
            return result;
            });
            }


            "These people looked deep within my soul and assigned me a number based on the order in which I joined." - Homer

            B Offline
            B Offline
            Bernhard Hiller
            wrote on last edited by
            #5

            Perfect! That hack really works. (But I still will need some time to find out how it works...) :thumbsup:

            Oh sanctissimi Wilhelmus, Theodorus, et Fredericus!

            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