WebClient DownloadFileComplete not called when using PublishSingleFile
Platform : console
This script is trying to download file from url using WebClient.
When finishing to download WebClient should call DownloadComplete method.
this method contains printing OK and toggles Locker variable.
then Locker releases execution loop, then printing finished.
When complete to download file to application's location, then it prints finished.
When using PublishSingleFile features then WebClient doesn't calling DownloadComplete method in builded application.
.csproj config<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp3.1</TargetFramework>
<PublishSingleFile>true</PublishSingleFile>
</PropertyGroup>
</Project>
using System;
using System.ComponentModel;
using System.Diagnostics;
using System.IO;
using System.Net;
namespace Test
{
class Program
{
static bool Locker;
static void Main(string[] args)
{
string ExecutionDirectory;
ExecutionDirectory = Path.GetDirectoryName(Process.GetCurrentProcess().MainModule.FileName);
//ExecutionDirectory = Path.GetDirectoryName(System.Reflection.Assembly.GetEntryAssembly().Location);
Console.WriteLine(ExecutionDirectory);
using (var w = new WebClient()) {
w.DownloadFileCompleted += DownloadCompleted;
w.DownloadFileAsync(new Uri("https://creft.me/cretapark/hi.png"), Path.Combine(ExecutionDirectory, "test.png"));
while (!Locker) ;
}
Console.WriteLine("finished");
Console.ReadLine();
}
private static void DownloadCompleted(object sender, AsyncCompletedEventArgs e)
{
Console.WriteLine("OK");
Locker = true;
}
}
}
dotnet --info.NET Core SDK(global.json 반영):
Version: 3.1.101
Commit: b377529961
런타임 환경:
OS Name: Windows
OS Version: 10.0.18363
OS Platform: Windows
RID: win10-x64
Base Path: C:\Program Files\dotnet\sdk\3.1.101\
Host (useful for support):
Version: 3.1.1
Commit: a1388f194c
.NET Core SDKs installed:
2.2.107 [C:\Program Files\dotnet\sdk]
2.2.300 [C:\Program Files\dotnet\sdk]
3.1.101 [C:\Program Files\dotnet\sdk]
.NET Core runtimes installed:
Microsoft.AspNetCore.All 2.2.5 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.All]
Microsoft.AspNetCore.App 2.2.5 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.AspNetCore.App 3.1.1 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.NETCore.App 2.2.5 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.NETCore.App 3.1.1 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.WindowsDesktop.App 3.1.1 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
I'm not able to reproduce what you describing as the cause - I am able to reproduce the symptoms. You can reproduce the problem in a Release build of the executable, for example using dotnet run -c Release.
The issue is that your Locker field needs to be volatile:
static volatile bool Locker;
That will fix the symptoms you are seeing.
Ok I tried to set volatile to Locker then it works good now!
But I'm curious why this is works fine without volatile when isn't PublishSingleFile?
But I'm curious why this is works fine without volatile when isn't PublishSingleFile?
PublishSingleFile isn't the cause of the issue it seems - it's a Debug vs. a Release build. You can reproduce the issue without using PublishSingleFile using a Release build - I just suspect that when you are publishing, you are publishing a Release build.
The volatile is required because you are changing a field from another thread - the thread that is doing the while(!Locker) doesn't "see" the other thread changing the field.
To clarify one thing - DownloadFileComplete was getting called. The problem is the while(!Locker) thread was caching the value of Locker so it was continuing to loop even though another thread modified it to true.
I got it, so then their sharing same origin variables in Debug mode? :O
I got it, so then their sharing same origin variables in Debug mode?
Volatile means that the JIT, CPU, and other parts of the program are aware that a memory location can be changed by a different thread. Without the volatile keyword there, the code with the while loop keeps the value cached somewhere.
This only happens in Release builds because only certain optimizations kick in when compiled for release.
Thanks for explain about thread cache!
This is very disappointing about less describe WebClient's funtionallity...
I was confused by the inconsistent behavior in release and debug mode, and I searched for it on the Internet (WebClient), but I didn't mention it anywhere, so I thought it was a bug in .NET.
Thank you for your kind attention, even though you are busy, l'll close this issue.