草庐IT

c# - 需要对我解决此 Winforms 竞争条件的第二(和第三)意见

coder 2024-05-28 原文

在博客等方面有上百个例子,说明如何实现一个记录前台 GUI 元素或为前台 GUI 元素提供状态的后台 worker 。它们中的大多数都包含一种方法来处理在生成工作线程和使用 ShowDialog() 创建前台对话框之间存在的竞争条件。但是,我想到一个简单的方法是强制在表单构造函数中创建句柄,这样线程将无法在创建句柄之前触发表单上的 Invoke/BeginInvoke 调用。

考虑一个使用后台工作线程记录到前台的 Logger 类的简单示例。

还假设我们不希望 NLog 或其他一些重量级框架来做一些如此简单和轻量级的事情。

我的记录器窗口由前台线程使用 ShowDialog() 打开,但仅在后台“工作”线程启动之后。工作线程调用 logger.Log(),后者本身使用 logForm.BeginInvoke() 在前台线程上正确更新日志控件。

  public override void Log(string s)
  {
     form.BeginInvoke(logDelegate, s);
  }

其中 logDelegate 只是“form.Log()”或其他一些可能更新进度条的代码的简单包装器。

问题在于存在的竞争条件;当后台工作线程在调用前台 ShowDialog() 之前开始记录时,表单的句柄尚未创建,因此 BeginInvoke() 调用失败。

我熟悉各种方法,包括使用表单 OnLoad 事件和计时器来创建暂停的工作任务,直到 OnLoad 事件生成一个计时器消息,该消息在显示表单后启动任务,或者如前所述,使用消息队列。但是,我认为简单地强制对话框的句柄在早期(在构造函数中)创建确保没有竞争条件,假设线程是由创建对话框的同一线程产生的。

http://msdn.microsoft.com/en-us/library/system.windows.forms.control.handle(v=vs.71).aspx

MSDN 说:“如果尚未创建句柄,引用此属性将强制创建句柄。”

所以我的记录器包装了一个表单,它的构造函数做了:

   public SimpleProgressDialog() {
       var h = form.Handle; // dereference the handle
   }

解决方案似乎太简单而不正确。我对为什么看似过于简单的解决方案使用安全或不安全特别感兴趣。

有什么意见吗?我还缺少其他东西吗?

编辑:我不是在寻求替代方案。不问如何使用 NLog 或 Log4net 等。如果我问的话,我会写一个关于此应用程序的所有客户限制等的页面。

从投票的数量来看,还有很多其他人也想知道答案。

最佳答案

如果您担心引用 Control.Handle 依赖副作用来创建句柄,您可以简单地调用 Control.CreateControl() 来创建它.但是,引用该属性的好处是,如果它已经存在,则无需对其进行初始化。

至于假设句柄已创建是否安全,您是正确的:只要在同一线程上生成后台任务之前创建句柄,就可以避免竞争条件。

关于c# - 需要对我解决此 Winforms 竞争条件的第二(和第三)意见,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6796413/

有关c# - 需要对我解决此 Winforms 竞争条件的第二(和第三)意见的更多相关文章

  1. ruby - 我需要将 Bundler 本身添加到 Gemfile 中吗? - 2

    当我使用Bundler时,是否需要在我的Gemfile中将其列为依赖项?毕竟,我的代码中有些地方需要它。例如,当我进行Bundler设置时:require"bundler/setup" 最佳答案 没有。您可以尝试,但首先您必须用鞋带将自己抬离地面。 关于ruby-我需要将Bundler本身添加到Gemfile中吗?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/4758609/

  2. ruby - rspec 需要 .rspec 文件中的 spec_helper - 2

    我注意到像bundler这样的项目在每个specfile中执行requirespec_helper我还注意到rspec使用选项--require,它允许您在引导rspec时要求一个文件。您还可以将其添加到.rspec文件中,因此只要您运行不带参数的rspec就会添加它。使用上述方法有什么缺点可以解释为什么像bundler这样的项目选择在每个规范文件中都需要spec_helper吗? 最佳答案 我不在Bundler上工作,所以我不能直接谈论他们的做法。并非所有项目都checkin.rspec文件。原因是这个文件,通常按照当前的惯例,只

  3. ruby - 如何在 Lion 上安装 Xcode 4.6,需要用 RVM 升级 ruby - 2

    我实际上是在尝试使用RVM在我的OSX10.7.5上更新ruby,并在输入以下命令后:rvminstallruby我得到了以下回复:Searchingforbinaryrubies,thismighttakesometime.Checkingrequirementsforosx.Installingrequirementsforosx.Updatingsystem.......Errorrunning'requirements_osx_brew_update_systemruby-2.0.0-p247',pleaseread/Users/username/.rvm/log/138121

  4. ruby - 如何根据特征实现 FactoryGirl 的条件行为 - 2

    我有一个用户工厂。我希望默认情况下确认用户。但是鉴于unconfirmed特征,我不希望它们被确认。虽然我有一个基于实现细节而不是抽象的工作实现,但我想知道如何正确地做到这一点。factory:userdoafter(:create)do|user,evaluator|#unwantedimplementationdetailshereunlessFactoryGirl.factories[:user].defined_traits.map(&:name).include?(:unconfirmed)user.confirm!endendtrait:unconfirmeddoenden

  5. ruby - 在 Ruby 中有条件地定义函数 - 2

    我有一些代码在几个不同的位置之一运行:作为具有调试输出的命令行工具,作为不接受任何输出的更大程序的一部分,以及在Rails环境中。有时我需要根据代码的位置对代码进行细微的更改,我意识到以下样式似乎可行:print"Testingnestedfunctionsdefined\n"CLI=trueifCLIdeftest_printprint"CommandLineVersion\n"endelsedeftest_printprint"ReleaseVersion\n"endendtest_print()这导致:TestingnestedfunctionsdefinedCommandLin

  6. ruby - 定义方法参数的条件 - 2

    我有一个只接受一个参数的方法:defmy_method(number)end如果使用number调用方法,我该如何引发错误??通常,我如何定义方法参数的条件?比如我想在调用的时候报错:my_method(1) 最佳答案 您可以添加guard在函数的开头,如果参数无效则引发异常。例如:defmy_method(number)failArgumentError,"Inputshouldbegreaterthanorequalto2"ifnumbereputse.messageend#=>Inputshouldbegreaterthano

  7. c# - 如何在 ruby​​ 中调用 C# dll? - 2

    如何在ruby​​中调用C#dll? 最佳答案 我能想到几种可能性:为您的DLL编写(或找人编写)一个COM包装器,如果它还没有,则使用Ruby的WIN32OLE库来调用它;看看RubyCLR,其中一位作者是JohnLam,他继续在Microsoft从事IronRuby方面的工作。(估计不会再维护了,可能不支持.Net2.0以上的版本);正如其他地方已经提到的,看看使用IronRuby,如果这是您的技术选择。有一个主题是here.请注意,最后一篇文章实际上来自JohnLam(看起来像是2009年3月),他似乎很自在地断言RubyCL

  8. C# 到 Ruby sha1 base64 编码 - 2

    我正在尝试在Ruby中复制Convert.ToBase64String()行为。这是我的C#代码:varsha1=newSHA1CryptoServiceProvider();varpasswordBytes=Encoding.UTF8.GetBytes("password");varpasswordHash=sha1.ComputeHash(passwordBytes);returnConvert.ToBase64String(passwordHash);//returns"W6ph5Mm5Pz8GgiULbPgzG37mj9g="当我在Ruby中尝试同样的事情时,我得到了相同sha

  9. ruby - 为什么在 ruby​​ 中创建 Rational 不需要新方法 - 2

    这个问题在这里已经有了答案:关闭10年前。PossibleDuplicate:Rubysyntaxquestion:Rational(a,b)andRational.new!(a,b)我正在阅读ruby镐书,我对创建有理数的语法感到困惑。Rational(3,4)*Rational(1,2)产生=>3/8为什么Rational不需要new方法(我还注意到例如我可以在没有new方法的情况下创建字符串)?

  10. 屏幕录制为什么没声音?检查这2项,轻松解决 - 2

    相信很多人在录制视频的时候都会遇到各种各样的问题,比如录制的视频没有声音。屏幕录制为什么没声音?今天小编就和大家分享一下如何录制音画同步视频的具体操作方法。如果你有录制的视频没有声音,你可以试试这个方法。 一、检查是否打开电脑系统声音相信很多小伙伴在录制视频后会发现录制的视频没有声音,屏幕录制为什么没声音?如果当时没有打开音频录制,则录制好的视频是没有声音的。因此,建议在录制前进行检查。屏幕上没有声音,很可能是因为你的电脑系统的声音被禁止了。您只需打开电脑系统的声音,即可录制音频和图画同步视频。操作方法:步骤1:点击电脑屏幕右下侧的“小喇叭”图案,在上方的选项中,选择“声音”。 步骤2:在“声

随机推荐