以下是一个完整的控制台程序,它重现了我遇到的一个奇怪的错误。该程序读取一个包含远程文件 url 的文件,每行一个。它启动 50 个线程来下载它们。
static void Main(string[] args)
{
try
{
string filePath = ConfigurationManager.AppSettings["filePath"],
folder = ConfigurationManager.AppSettings["folder"];
Directory.CreateDirectory(folder);
List<string> urls = File.ReadAllLines(filePath).Take(10000).ToList();
int urlIX = -1;
Task.WaitAll(Enumerable.Range(0, 50).Select(x => Task.Factory.StartNew(() =>
{
while (true)
{
int curUrlIX = Interlocked.Increment(ref urlIX);
if (curUrlIX >= urls.Count)
break;
string url = urls[curUrlIX];
try
{
var req = (HttpWebRequest)WebRequest.Create(url);
using (var res = (HttpWebResponse)req.GetResponse())
using (var resStream = res.GetResponseStream())
using (var fileStream = File.Create(Path.Combine(folder, Guid.NewGuid() + url.Substring(url.LastIndexOf('.')))))
resStream.CopyTo(fileStream);
}
catch (Exception ex)
{
Console.WriteLine("Error downloading img: " + url + "\n" + ex);
continue;
}
}
})).ToArray());
}
catch
{
Console.WriteLine("Something bad happened.");
}
}
在我的本地计算机上它工作正常。在服务器上,下载数百张图片后,显示错误 Attempted to read or write protected memory 或 Unable to read data from the transport connection: A blocking operation was interrupted by调用 WSACancelBlockingCall。。
这似乎是一个原生错误,因为内部和外部catch 都没有捕获到它。我从未见过 发生了不好的事情。。
我在 WinDbg 中运行它,它显示如下:
(3200.1790): Access violation - code c0000005 (first chance)
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
LavasoftTcpService64+0x765f:
00000001`8000765f 807a1900 cmp byte ptr [rdx+19h],0 ds:baadf00d`0000001a=??
0:006> g
(3200.326c): CLR exception - code e0434352 (first chance)
(3200.326c): CLR exception - code e0434352 (first chance)
(3200.2b9c): Access violation - code c0000005 (!!! second chance !!!)
LavasoftTcpService64!WSPStartup+0x9749:
00000001`8002c8b9 f3a4 rep movs byte ptr [rdi],byte ptr [rsi]
我刚刚关闭了 Lavasoft,现在 WinDbg 显示如下:
Critical error detected c0000374
(3c4.3494): Break instruction exception - code 80000003 (first chance)
ntdll!RtlReportCriticalFailure+0x4b:
00007fff`4acf1b2f cc int 3
0:006> g
(3c4.3494): Unknown exception - code c0000374 (first chance)
(3c4.3494): Unknown exception - code c0000374 (!!! second chance !!!)
ntdll!RtlReportCriticalFailure+0x8c:
00007fff`4acf1b70 eb00 jmp ntdll!RtlReportCriticalFailure+0x8e (00007fff`4acf1b72)
0:006> g
WARNING: Continuing a non-continuable exception
(3c4.3494): C++ EH exception - code e06d7363 (first chance)
HEAP[VIPJobsTest.exe]: HEAP: Free Heap block 0000007AB96CC5D0 modified at 0000007AB96CC748 after it was freed
(3c4.3494): Break instruction exception - code 80000003 (first chance)
ntdll!RtlpBreakPointHeap+0x1d:
00007fff`4acf3991 cc int 3
最佳答案
您的异常不会抛出,因为您并没有尝试获取它。 WaitAll方法基本上是一个 Barrier ,等待(哈哈)所有任务完成。这是void ,因此您必须为您的任务保存一个引用以供进一步操作,如下所示:
var tasks = Enumerable.Range(0, 50).Select(x => Task.Factory.StartNew(() =>
{
while (true)
{
// ..
try
{
// ..
}
catch (Exception ex)
{
// ..
}
}
})).ToArray();
Task.WaitAl((tasks);
// investigate exceptions here
var faulted = tasks.Where(t => t.IsFaulted);
根据MSDN ,当您使用静态或实例之一时传播异常 Task.Wait 或 Task<TResult>.Wait 方法,或 .Result 属性(property)。但是,这不是您的选择,因为您正在使用 try/catch这里。所以你需要订阅 TaskScheduler.UnobservedTaskException 事件:
TaskScheduler.UnobservedTaskException += TaskScheduler_UnobservedTaskException;
static void TaskScheduler_UnobservedTaskException(object sender, UnobservedTaskExceptionEventArgs e)
{
Console.WriteLine("Error." + e);
e.SetObserved();
}
为什么不抛出就跑?
This application domain-wide event provides a mechanism to prevent exception escalation policy (which, by default, terminates the process) from triggering.
To make it easier for developers to write asynchronous code based on tasks, the
.NET Framework 4.5changes the default exception behavior for unobserved exceptions. Although unobserved exceptions still raise theUnobservedTaskExceptionexception, the process does not terminate by default. Instead, the exception is handled by the runtime after the event is raised, regardless of whether an event handler observes the exception. This behavior can be configured. Starting with the.NET Framework 4.5, you can use the configuration element to revert to the behavior of the .NET Framework 4 and terminate the process:<configuration> <runtime> <ThrowUnobservedTaskExceptions enabled="true"/> </runtime> </configuration>
现在,回到您的代码。考虑使用静态 HttpClient实例而不是 HttpWebRequest ,因为您只需要一个结果字符串。此类设计用于多线程代码,因此它的方法是线程安全的。
另外,您应该提供 TaskCreationOptions.LongRunning 标记你的 StartNew方法(which is dangerous,顺便说一下,但您仍然需要它):
Specifies that a task will be a long-running, coarse-grained operation involving fewer, larger components than fine-grained systems. It provides a hint to the
TaskSchedulerthat oversubscription may be warranted.Oversubscription lets you create more threads than the available number of hardware threads. It also provides a hint to the task scheduler that an additional thread might be required for the task so that it does not block the forward progress of other threads or work items on the local thread-pool queue.
关于c# - catch 没有捕获到多线程错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42987919/
大约一年前,我决定确保每个包含非唯一文本的Flash通知都将从模块中的方法中获取文本。我这样做的最初原因是为了避免一遍又一遍地输入相同的字符串。如果我想更改措辞,我可以在一个地方轻松完成,而且一遍又一遍地重复同一件事而出现拼写错误的可能性也会降低。我最终得到的是这样的:moduleMessagesdefformat_error_messages(errors)errors.map{|attribute,message|"Error:#{attribute.to_s.titleize}#{message}."}enddeferror_message_could_not_find(obje
我好像记得Lua有类似Ruby的method_missing的东西。还是我记错了? 最佳答案 表的metatable的__index和__newindex可以用于与Ruby的method_missing相同的效果。 关于ruby-难道Lua没有和Ruby的method_missing相媲美的东西吗?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/7732154/
我有一个奇怪的问题:我在rvm上安装了rubyonrails。一切正常,我可以创建项目。但是在我输入“railsnew”时重新启动后,我有“程序'rails'当前未安装。”。SystemUbuntu12.04ruby-v"1.9.3p194"gemlistactionmailer(3.2.5)actionpack(3.2.5)activemodel(3.2.5)activerecord(3.2.5)activeresource(3.2.5)activesupport(3.2.5)arel(3.0.2)builder(3.0.0)bundler(1.1.4)coffee-rails(
我想在一个没有Sass引擎的类中使用Sass颜色函数。我已经在项目中使用了sassgem,所以我认为搭载会像以下一样简单:classRectangleincludeSass::Script::FunctionsdefcolorSass::Script::Color.new([0x82,0x39,0x06])enddefrender#hamlengineexecutedwithcontextofself#sothatwithintemlateicouldcall#%stop{offset:'0%',stop:{color:lighten(color)}}endend更新:参见上面的#re
我遵循MichaelHartl的“RubyonRails教程:学习Web开发”,并创建了检查用户名和电子邮件长度有效性的测试(名称最多50个字符,电子邮件最多255个字符)。test/helpers/application_helper_test.rb的内容是:require'test_helper'classApplicationHelperTest在运行bundleexecraketest时,所有测试都通过了,但我看到以下消息在最后被标记为错误:ERROR["test_full_title_helper",ApplicationHelperTest,1.820016791]test
我收到这个错误:RuntimeError(自动加载常量Apps时检测到循环依赖当我使用多线程时。下面是我的代码。为什么会这样?我尝试多线程的原因是因为我正在编写一个HTML抓取应用程序。对Nokogiri::HTML(open())的调用是一个同步阻塞调用,需要1秒才能返回,我有100,000多个页面要访问,所以我试图运行多个线程来解决这个问题。有更好的方法吗?classToolsController0)app.website=array.join(',')putsapp.websiteelseapp.website="NONE"endapp.saveapps=Apps.order("
我是rails的新手,想在form字段上应用验证。myviewsnew.html.erb.....模拟.rbclassSimulation{:in=>1..25,:message=>'Therowmustbebetween1and25'}end模拟Controller.rbclassSimulationsController我想检查模型类中row字段的整数范围,如果不在范围内则返回错误信息。我可以检查上面代码的范围,但无法返回错误消息提前致谢 最佳答案 关键是您使用的是模型表单,一种显示ActiveRecord模型实例属性的表单。c
我正在尝试编写一个将文件上传到AWS并公开该文件的Ruby脚本。我做了以下事情:s3=Aws::S3::Resource.new(credentials:Aws::Credentials.new(KEY,SECRET),region:'us-west-2')obj=s3.bucket('stg-db').object('key')obj.upload_file(filename)这似乎工作正常,除了该文件不是公开可用的,而且我无法获得它的公共(public)URL。但是当我登录到S3时,我可以正常查看我的文件。为了使其公开可用,我将最后一行更改为obj.upload_file(file
我克隆了一个rails仓库,我现在正尝试捆绑安装背景:OSXElCapitanruby2.2.3p173(2015-08-18修订版51636)[x86_64-darwin15]rails-v在您的Gemfile中列出的或native可用的任何gem源中找不到gem'pg(>=0)ruby'。运行bundleinstall以安装缺少的gem。bundleinstallFetchinggemmetadatafromhttps://rubygems.org/............Fetchingversionmetadatafromhttps://rubygems.org/...Fe
在Cooper的书BeginningRuby中,第166页有一个我无法重现的示例。classSongincludeComparableattr_accessor:lengthdef(other)@lengthother.lengthenddefinitialize(song_name,length)@song_name=song_name@length=lengthendenda=Song.new('Rockaroundtheclock',143)b=Song.new('BohemianRhapsody',544)c=Song.new('MinuteWaltz',60)a.betwee