locked
WCF C++/CLI service method returning a result to a C# client. RRS feed

  • Question

  • I have a synchronous service method in C++/CLI service that returns a string. Building for Windows Store App client using the VS2012 "Add Reference" functionality I cannot find a way to retrieve the results.

    C++/CLI service:

    [System::ServiceModel::OperationContractAttribute]
    System::String^ GetNowPlaying();

    C# generated Reference.cs:

    [System.ServiceModel.OperationContractAttribute(Action="http://tempuri.org/PlaybackControl/GetNowPlaying", ReplyAction="http://tempuri.org/PlaybackControl/GetNowPlayingResponse")]
            System.Threading.Tasks.Task<string> GetNowPlayingAsync();

    C# calling implementation:

    //await keyword results in compile time error:
    //The 'await' operator can only be used within an async method.
    //Consider marking this method with the 'async' modifier and changing its return type to 'Task'.

    string x = await GetNowPlayingAsync();

    //ContinueWith results in a runtime error:
    //The application called an interface that was marshalled for a different thread. (Exception from HRESULT: 0x8001010E (RPC_E_WRONG_THREAD))

    System.Threading.Tasks.Task<string> task = GetNowPlayingAsync();
    task.ContinueWith(delegate
    {
        tbOutput.Text = task.Result;
    });

    Monday, October 21, 2013 6:16 AM

Answers

  • Which error do you mean? "//The 'await' operator can only be used within an async method."?

    This doesn't have anything to do with the service reference. You fix that by adding the async tag to the function you're calling await from:

    public async void DoSomething()
    {
    string nowPlaying = await GetNowPlayingAsync()
    await dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
    {
         tbOutput.Text = nowPlaying;
    });
    }

    I strongly recommend you go over the Asynchronous programming (Windows Store apps) section in the documentation.

    --Rob

    Tuesday, October 22, 2013 10:58 PM
    Moderator

All replies

  • System.Threading.Tasks.Task<string> task = GetNowPlayingAsync();

    task.ContinueWith(delegate
    {
        tbOutput.Text = task.Result;
    });

    Ok, task.ContinueWith works, the exception is because I'm trying to update the UI from another thread. So it appears ContinueWith requires a delegate which runs on another thread. Just curious, does "await" do that? or does it return back to the thread that calls the method. I guess the question is moot since it appears "await" doesn't work anyways.

    So, is ContinueWith the correct way to return values from a C++/CLI service in a C# Windows Store App client?

    Thanks.

    Monday, October 21, 2013 6:38 AM
  • Ok, so no one is responding, so I guess I will continue with my questions, since they still pertain to the original post. (previous questions still relevant)

    This post answers, to some degree, the issue of 'await' vs "other WinRT APIs":
    http://stackoverflow.com/questions/10579027/run-code-on-ui-thread-in-winrt

    One other question remains:
    How do I configure a WCF service method in C++/CLI that returns a result such that I can use the 'await' keyword on the WinRT client side?

    Thanks
    Tuesday, October 22, 2013 5:08 AM
  • Please be aware that bumping your post may make it less likely to get a prompt answer. It lowers the visibility of the post in our tools.

    Windows Store apps cannot use C++/CLI. They can connect to web services, but don't know or care how that service is implemented. On the other side, the web service doesn't know how the client is implemented and doesn't know or care if the client awaits. In other words: the web service implementation is irrelevant to the problem and nothing you change in it will affect how you handle the task on the client side.

    You don't give any context as to where you are calling GetNowPlayingAsync from, but from the threading error you get I expect it is not called from the UI thread. You can confirm this in the debugger. Await will call its continuation on the thread it was called from. UIElements require the UI thread, so you will need to call Dispatcher.RunAsync to marshal back to that thread:

    string nowPlaying = await GetNowPlayingAsync()
    await dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
    {
         tbOutput.Text = nowPlaying;
    });

    You can get the dispatcher object by calling CoreWindow.GetForCurrentThread().Dispatcher when on the UI thread.

    I strongly recommend you go over the Asynchronous programming (Windows Store apps) section in the documentation.

    --Rob

    Tuesday, October 22, 2013 5:43 AM
    Moderator
  • Hi Rob,

    Thanks for the response, sorry if my questions are ill defined. GetNowPlayingAsync is being called on the UI thread. The C++/CLI code is in the service, which is a desktop application, not the Windows Store App client. But as you point out, the client code should not care how the service is implemented, so the C++/CLI question is not valid. Also, the WCF binding is TCP/IP, if that makes a difference.

    Yes, the ContinueWith delegate is called from a non-UI Thread, which I suppose was spawned by the WCF generated Async code in Reference.cs.

    For now ContinueWith together with dispatcher.RunAsync works, but it is still not clear to me why I get the error I describe in the original post when I try to use 'await'. Is this a setting in a dialogue somewhere when I add the service reference?

    Thanks again.

    Tuesday, October 22, 2013 6:47 PM
  • Which error do you mean? "//The 'await' operator can only be used within an async method."?

    This doesn't have anything to do with the service reference. You fix that by adding the async tag to the function you're calling await from:

    public async void DoSomething()
    {
    string nowPlaying = await GetNowPlayingAsync()
    await dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
    {
         tbOutput.Text = nowPlaying;
    });
    }

    I strongly recommend you go over the Asynchronous programming (Windows Store apps) section in the documentation.

    --Rob

    Tuesday, October 22, 2013 10:58 PM
    Moderator