Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WCF Client (.net8.0 Win form Exe) Call will Hung if Sync Method is Invoked before Invoking any Async Method #5730

Open
Samba143 opened this issue Jan 20, 2025 · 7 comments
Assignees
Labels

Comments

@Samba143
Copy link

Samba143 commented Jan 20, 2025

Repro:

  1. Create WCF service with NetTCP binding with runtime as .Net framework 4.8
  2. Create WCF client (Win forms exe) using WCF client packages 8.1 and runtime as .Net 8.0

Image

Expected Results:
Both operations should return irrespective of the sequence of requests

Actual Results:
Scenario 1: If Sync call (button2_Click) is Invoked first, call never returns
Scenario 2: If Async call (button1_Click) is Invoked first and then Sync call (button_Click) is invoked, results are as expected
Scenario 3: Sync calls works fine provided async call was invoked at least once

No issue if client is running on .Net framework.
No issue if client is a console application on .Net 8.0

@mconnew , How to justify the above behavior with WCF client packages on .Net 8.0 ?
Your clarifications will help me to assess the feasibility of WCF client codebase migration to .Net 8.0

@Samba143 Samba143 changed the title WCF Client (.net8.0 Win form Exe) Call will Hung if Sync Method is Invoked WCF Client (.net8.0 Win form Exe) Call will Hung if Sync Method is Invoked before Invoking any Async Method Jan 20, 2025
@mconnew
Copy link
Member

mconnew commented Jan 30, 2025

I believe this is the same as a previously reported issue that I haven't got to fixing yet. If it is the same, there's an easy workaround. In button1_Click, call await Task.Yield() after the call to StartCountPassCounterAsync() completes. The problem was the continuation happened on a thread that the inner workings of WCF needed back to handle subsequent requests.
Another option that might work is changing your code to await client.StartCountPassCounterAsync().ConfigureAwait(false);.

@Samba143
Copy link
Author

@mconnew
I don't think this is same as previously reported issue.
My (client) requirement is just to work with sync calls only.
Async call I just tried as part of analysis and found some dependency between these two invocations and I dont know the rationale.

@mconnew
Copy link
Member

mconnew commented Jan 30, 2025

Are you able to provide a repro app? The only potential issue I'm aware of when it comes to UI apps we have explicit tests to validate that our methods to prevent it are working. Basically we only have an async implementation (earlier netcore days didn't have sync api's for anything IO) and sync calls are implemented using async and waiting on the result. The usual gotcha for this is when using a single threaded SynchonizationContext such as what WPF and WinForms uses, then the blocking Wait call on the Task prevents the async continuations from running. But we have logic which immediately jumps to a thread pool thread to prevent this. To see if this might be a variant I've missed, try doing this:

var ctx = SynchronizationContext.Current;
SynchronizationContext.SetSynchronizationContext(null);
try
{
    int result2 = client.StartCountPassCounter();
}
finally
{
    SynchronizationContext.SetSynchronizationContext(ctx);
}

If the problem goes away, then you are hitting a code path without that protection. If this "fixes" it, then I might be able to work out what's going on from a call stack from debugging. If it doesn't, then having a minimal repro app is the only way I'll be able to diagnose this.

@Samba143
Copy link
Author

@mconnew ,
Appreciate your quick feedback.
Yes, the code snippet working fine. I could invoke sync call and get the results

@mconnew
Copy link
Member

mconnew commented Jan 30, 2025

When it's blocked, could you get the call stack of that thread and post it here? I want to see which async method call isn't using a thread pool thread for continuation.

@Samba143
Copy link
Author

When it's blocked, could you get the call stack of that thread and post it here? I want to see which async method call isn't using a thread pool thread for continuation.

Image

@mconnew
Copy link
Member

mconnew commented Jan 31, 2025

I need the callstack of that main thread which has the WaitForCompletion call. The screenshot just shows me the last method on each thread.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants