1

Maybe I did not search correctly here in the forum because I did not find a similar problem.
Well, my problem is when I try to execute an async method inside a thread.

When I run the method (Register) without the thread it works perfectly! Below is an example of the scenario.

private SyncProcess _sync = new SyncProcess();
private static HttpClient _httpClient = new HttpClient();
private Thread _thread;

public class SyncProcess : ISyncProcess
{
    public event CompleteHandler OnComplete = delegate { };
    // another properties ...

    public void Run()
    {
        // import rules
        // ...
        OnComplete();
    }
}

public void TestImport()
{
    Register(idsync, "start"); // here register works fine
    _sync.OnComplete += ImportComplete;
    _thread = new Thread(() =>
    {
        try
        {
            _sync.Run();
        }
        catch (Exception ex)
        {
            // not fall here
        }
    });
    //
    _thread.Start();
}

private void ImportComplete()
{
    // other end-of-import rules
    // ...
    Register(idsync, "complete");  // here register not works
}

public async Task<string> Register(int idsync, string type)
{
    string url = "myurl";
    var stringContent = new FormUrlEncodedContent(new[] { new KeyValuePair<string, string>("json", "myjson") }); 
    var response = await _httpClient.PostAsync(url + type, stringContent);
    if (response.IsSuccessStatusCode)
    {
        // do something
    }
    return "";
}

The problem occurs when I call the method (Register) inside the thread, another thing is that is that it does not generate error does not fall into the try, the debugging simply terminates. I've tried adding try code everywhere but never crashed in catch.
Debug always aborts on the following line:

var response = await _httpClient.PostAsync(url + type, stringContent);


What should I do in this case?

Updated the code returning string in the Register method, but the same error remains.
Thanks any suggestions!  

Alexandre Neukirchen
  • 2,713
  • 7
  • 26
  • 36
  • 3
    You are using async void. Could it be that the application dies before it finishes executing? – Vlad Feb 26 '19 at 12:41
  • @Vlad, We do not have the need to validate the return, just to do the `http` request, the return does not matter! – Alexandre Neukirchen Feb 26 '19 at 12:52
  • Would like to see a sample project which recreates the problem so I can improve my answer. – Lloyd Feb 26 '19 at 12:54
  • Can you please provide a [mcve]? I would like to be able to copy, paste, and run your code in a console app and see the issue you're getting. – Enigmativity Feb 28 '19 at 00:32
  • @Enigmativity, I tried to reproduce the error in a simplified environment. However, in the minimalist environment the error does not occur. https://github.com/AlexandreNeuk/ConsoleApplication1.git – Alexandre Neukirchen Mar 04 '19 at 12:20
  • @AlexandreNeukirchen - Then we can't answer the question. You need to get a working [mcve]. It's very likely in the process of producing one you'll answer your own question. – Enigmativity Mar 04 '19 at 12:25
  • Sorry, but it really is very complicated to reproduce the problem because it involves the integration between different databases, dependencies among other projects and legal issues of copying and reproduction. Currently the problem has been bypassed using System.Net.Http.HttpClient.PostAsync to register the start, and System.Net.WebClient.UploadString to register the end. But I did not like this solution, and I'm trying to solve the problem in a smarter way. – Alexandre Neukirchen Mar 04 '19 at 12:42

2 Answers2

4

Your problem is due to the use of async void, which should be avoided. One of its problems is that you can't catch exceptions using try/catch.

Event handlers in C# are a "fire-and-forget" kind of language feature. In particular, asynchronous event handlers must use async void, and this means the event-publishing code cannot see those exceptions. If you want to allow async event handlers and handle exceptions (or other results) from them, you can use a "deferral" solution or make your event handler delegate return Task instead.

Stephen Cleary
  • 437,863
  • 77
  • 675
  • 810
1

Async void will not allow you to catch any exceptions and will terminate your application when one is thrown. Exceptions are only observed and handled as normal exceptions when using task instead of void.

You can read all about it here link

I can not answer your first question on why it works without the thread without more information. I can guarantee you thought that it has nothing to do with multi threading as far as I know since the main thread is also just a thread like any other.

Lloyd
  • 1,119
  • 10
  • 29