添加链接
link之家
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接
相关文章推荐
捣蛋的牙膏  ·  Android RecyclerView ...·  3 周前    · 
听话的棒棒糖  ·  .net ...·  5 月前    · 
var filenames = new List(); var wc = new WebClient(); var progressPerUrl = 100 / (float)urls.Count; for (var i = 0; i < urls.Count; i++) var url = urls[i]; wc.Headers.Add("User-Agent", "User-Agent: CoolTool/0.0 (https://example.org/cool-tool/; cool-tool@example.org) generic-library/0.0"); var filename = $"out-{i}.jpg"; filenames.Add(filename); wc.DownloadProgressChanged += (ee, sender) => { var urlProgressStart = progressPerUrl * i; progressBarText1.Value = (int)(urlProgressStart + progressPerUrl * sender.ProgressPercentage / 100f); await wc.DownloadFileTaskAsync(url, filename); var saveTasks = new List(); foreach (var filename in filenames) saveTasks.Add(Task.Run(() => { var newFilename = @"d:\satImages\satImage" + counter + ".gif"; Image.FromFile(filename).Save(newFilename, ImageFormat.Gif); counter++; await Task.WhenAll(saveTasks);

For some reason without any break point I'm getting the exception error :

System.Reflection.TargetInvocationException: 'Exception has been thrown by the target of an invocation.'

But if I put a break point on the line :

saveTasks.Add(Task.Run(() => {  

And click continue each time when it finish(10 images) it's moving to the last line :

await Task.WhenAll(saveTasks);  

And everything is fine.

But without a break point it's throwing the exception :

ExternalException: A generic error occurred in GDI+.

This exception was originally thrown at this call stack:
System.Drawing.Image.Save(string, System.Drawing.Imaging.ImageCodecInfo, System.Drawing.Imaging.EncoderParameters)
System.Drawing.Image.Save(string, System.Drawing.Imaging.ImageFormat)
Extract.Form1.OnLoad.AnonymousMethod__1() in Form1.cs
System.Threading.Tasks.Task.InnerInvoke()
System.Threading.Tasks.Task.Execute()
System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(System.Threading.Tasks.Task)
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(System.Threading.Tasks.Task)
Extract.Form1.OnLoad(System.EventArgs) in Form1.cs
System.Runtime.CompilerServices.AsyncMethodBuilderCore.ThrowAsync.AnonymousMethod__6_0(object)

The full details :

System.Reflection.TargetInvocationException
HResult=0x80131604
Message=Exception has been thrown by the target of an invocation.
Source=mscorlib
StackTrace:
at System.RuntimeMethodHandle.InvokeMethod(Object target, Object[] arguments, Signature sig, Boolean constructor)
at System.Reflection.RuntimeMethodInfo.UnsafeInvokeInternal(Object obj, Object[] parameters, Object[] arguments)
at System.Delegate.DynamicInvokeImpl(Object[] args)
at System.Windows.Forms.Control.InvokeMarshaledCallbackDo(ThreadMethodEntry tme)
at System.Windows.Forms.Control.InvokeMarshaledCallbackHelper(Object obj)
at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
at System.Windows.Forms.Control.InvokeMarshaledCallback(ThreadMethodEntry tme)
at System.Windows.Forms.Control.InvokeMarshaledCallbacks()
at System.Windows.Forms.Control.WndProc(Message& m)
at System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m)
at System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
at System.Windows.Forms.NativeWindow.DebuggableCallback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
at System.Windows.Forms.UnsafeNativeMethods.DispatchMessageW(MSG& msg)
at System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(IntPtr dwComponentID, Int32 reason, Int32 pvLoopData)
at System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(Int32 reason, ApplicationContext context)
at System.Windows.Forms.Application.ThreadContext.RunMessageLoop(Int32 reason, ApplicationContext context)
at System.Windows.Forms.Application.Run(Form mainForm)
at Extract.Program.Main() in D:\Csharp Projects\Extract\Program.cs:line 19

This exception was originally thrown at this call stack:
System.Drawing.Image.Save(string, System.Drawing.Imaging.ImageCodecInfo, System.Drawing.Imaging.EncoderParameters)
System.Drawing.Image.Save(string, System.Drawing.Imaging.ImageFormat)
Extract.Form1.OnLoad.AnonymousMethod__1() in Form1.cs
System.Threading.Tasks.Task.InnerInvoke()
System.Threading.Tasks.Task.Execute()
System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(System.Threading.Tasks.Task)
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(System.Threading.Tasks.Task)
Extract.Form1.OnLoad(System.EventArgs) in Form1.cs
System.Runtime.CompilerServices.AsyncMethodBuilderCore.ThrowAsync.AnonymousMethod__6_0(object)

Inner Exception 1:
ExternalException: A generic error occurred in GDI+.

The error itself is likely caused by that program attempting to write to the same file location for every filename. The reason for this is that the code that's ran inside of Task.Run isn't necessarily ran immediately. All that code does is schedule some work to be done with the ThreadPool:
https://learn.microsoft.com/en-us/dotnet/api/system.threading.tasks.task.run?view=net-5.0

So the loop has already iterated to the end (having incremented 10 times) by the time that the inner function has even run. The result is that every instance attempts to write to satImage11.gif. The fix is to make a copy of that global counter value to a variable that won't change, then use that inside the Task.Run callback instead, and it'll keep it's original value.

   foreach (var filename in filenames) {  
   	var counterCopy = counter;  
   	saveTasks.Add(Task.Run(() => {  
   		var newFilename = @"c:\bla\satImage" + counterCopy + ".gif";  
   		Image.FromFile(filename).Save(newFilename, ImageFormat.Gif);  
   	counter++;