问题标签 [synchronizationcontext]

For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.

0 投票
1 回答
1389 浏览

c# - SynchronizationContext.Post 在 BackgroundWorker 中不起作用

我正在使用后台工作人员来完成我的所有处理。在那里,我有很多地方可以写入“日志”文本框。所有这些工作都很好,但在后台工作人员的最后,最后一行,我还有一个SynchronizationContext不会触发的呼叫。为什么所有其他调用都有效,而不是最后一个?

我应该补充一点,应用程序只是“挂起”,甚至还有一个 EventLog 条目说:

这是DoWork方法(在调用时执行RunWorkerAsync):

您会注意到,在foreach循环结束时,我写了说Finished the compare...,并且确实写了,但是下一个同步调用:

永远不会被处决。这是那个方法:

0 投票
2 回答
574 浏览

c# - 在c#中从不同的类实例化线程方法

有人可以指出我如何处理以下问题吗?基本上,我试图重用以下示例中的代码:http: //www.codeproject.com/KB/threads/SynchronizationContext.aspx 我唯一不明白的问题是,如果在一个不同的班级。请看下面的代码。

编辑:

例如,运行方法是由其他人(另一个开发人员)给我的,我需要在我的 UI 线程(主线程或 Form1 类)中将这个方法作为不同的线程运行,但是,每当我运行线程(运行方法)我还需要mListBox使用 UpdateUI 方法更新 ListBox。

0 投票
2 回答
2285 浏览

c# - 跨线程交互 c#

有人可以帮助我如何在我的类中设置 Thread.join() 方法,或者是否有一种巧妙的方法来处理SynchronizationContext类和thread.join方法。基本上,我试图从不同的线程(不是 UI 线程)每 2 秒更新一次数据网格视图(dgv)单元格和进度条(pb)。当一个线程完成工作时,该功能可以正常工作;但是,我想设置 2 个线程,以便第一个线程(线程 1)将更新控件(在我的情况下,它将更新 datagridview 并显示 10 行,进度条将更新为 50%)。一旦线程 1 完成其工作,线程 2 应该启动并更新控件(在我的情况下,它将更新 datagridview 并显示 10 更多行,进度条将更新为 100%)。请看下面的代码。

0 投票
2 回答
2506 浏览

c# - 为什么 TaskScheduler.FromCurrentSynchronizationContext 在 Monotouch 中不同步?

我感兴趣的是为什么我们需要调用 InvokeOnMainThread 而这将是 TaskScheduler.FromCurrentSynchronizationContext() 的主要意图和责任?

我在 Monotouch 中为 iPhone 应用程序使用 TPL 来执行一些后台任务并通过记者类更新 UI。但似乎 TaskScheduler.FromCurrentSynchronizationContext() 没有像您期望的那样与 UI 线程同步。此时,我设法通过使用 InvokeOnMainThread 使其工作(但仍然感觉不对),如Xamarin 网站上的线程主题所述。

我还在 BugZilla 上发现了一个报告的(类似)错误,似乎已经解决了。还有另一个关于在 MonoTouch 中使用后台线程的首选方式的线程问题。

下面是用于说明我的问题并显示行为的代码片段。

而记者类有这些方法

应用程序输出窗口中的结果将是:

如您所见,“在线程 6 中工作”很好。报告也在线程 6 上,这是错误的。有趣的是,RegisterContinuation它在线程 1 中进行了报告!!!


进展:我还没有弄清楚这个..有人吗?

0 投票
1 回答
298 浏览

.net - Windows 服务的 .net 组件中的 AsyncOperationManager

我们开发了一个非常适合 WinForms 的 .Net 组件。该组件使用 aSynchronizationContext从底层线程编组到 UI 线程引发事件(当然组件会WindowsFormsSynchronizationContext自动获取并使用它将事件发布到应用程序的 UI 线程)。

现在我们要创建一个重用这个组件的 nt 服务。由于 Windows 服务不SynchronizationContext自动提供,我认为我们可以使用AsyncOperationManager(和它的SynchronizationContext)来将在该组件的底层线程中触发的所有事件编组到单个处理器线程。这是一个好方法吗?

在我的测试中,我使用AsyncOperationManager.CreateOperation(null);来自不同线程的调用来检查发布的异步操作的行为(一个执行MyService.OnStart()方法......和另一个我在我的服务中运行的内部处理线程)。令我惊讶的是,发布的异步操作的线程 ID 始终是执行该MyService.OnStart()方法的线程 ID,因此可能是 SCM 线程。

MSDN 上没有关于此的文档,但我认为调用的线程AsyncOperationManager.CreateOperation将是异步操作将被编组到的线程。

有人可以在这里阐明一下吗?AsyncOperationManager另外,您会发现我在 Windows 服务中使用它的意图有什么问题吗?还有哪些方法?

0 投票
1 回答
6328 浏览

c# - SynchronizationContext.Current 在主 UI 线程上的 Continuation 中为 null

我一直在尝试在 Winforms 应用程序中追踪以下问题:在
主线程上运行SynchronizationContext.Current的任务延续(即.ContinueWith)中为空(我希望当前同步上下文为System.Windows.Forms.WindowsFormsSynchronizationContext)。

这是演示该问题的 Winforms 代码:

这对我来说是个问题,因为我尝试BackgroundWorker从延续中使用,BackgroundWorker 将使用当前的 SynchronizationContext 作为其事件RunWorkerCompletedProgressChanged. 由于当我启动 BackgroundWorker 时当前 SynchronizationContext 为空,因此事件不会按我的意愿在主 ui 线程上运行。

我的问题:
这是微软代码中的错误,还是我在某个地方犯了错误?

附加信息:

  • 我正在使用 .Net 4.0(我还没有在 .NET 4.5 RC 上尝试过)
  • 我可以在任何 x86/x64/Any CPU(在 x64 机器上)上的 Debug/Release 上重现这一点。
  • 它始终如一地重现(如果有人无法重现它,我会很感兴趣)。
  • 我有使用 BackgroundWorker 的遗留代码——所以我不能轻易改用不使用 BackgroundWorker
  • 我已经确认代码在MyContinueWith主 ui 线程上运行。
  • 我不确切知道为什么StartLogicalOperation调用会导致问题,这正是我在我的应用程序中缩小范围的原因。
0 投票
0 回答
495 浏览

c# - 从后台工作人员返回到从 Winforms 应用程序中托管的 WPF 对话框调用线程

我们有一个 Winforms 应用程序,它启动一个 WPF 对话框,我将其称为向导。该向导的目的是打开多个文本文件并将其内容保存到数据库中。将这些文件保存到数据库所需的时间从 15 到 60+ 秒不等。为了给向导 UI 响应,将文本文件保存到数据库的过程在 BackgroundWorker 线程上完成。不幸的是,由于 Winforms 宿主应用程序中的一些遗留代码,向导在 80 - 90% 的时间里完全没有响应。因此,向导在其自己的工作线程上启动。

所以总的来说我们有三个主线程,支持Winforms主机的主线程、向导线程和BackgroundWorker线程。用户可以通过单击向 BackgroundWorker 线程发送 CancelAsync 消息的向导上的按钮来暂停此导出过程。在 BackgroundWorker_DoWork 事件处理程序中,我们检查此取消消息,如果找到,则停止处理并返回。这会触发 BackgroundWorker_RunWorkerCompleted 事件处理程序,我可以在其中检查使用 Thread.CurrentThread.Name 已将控制权返回到的线程的标识。

用户第一次暂停 BackgroundWorker 进程时,控制权返回给 Wizard 线程。如果用户想要恢复导出过程,我们调用 RunWorkerAsync 依次启动 BackgroundWorker_DoWork 事件处理程序。从观察中我可以看到,这个处理程序没有使用它之前使用的同一个线程,而是使用了线程池中的一个新线程。出于调试目的,我给这个线程一个名字。

第一个 BackgroundWorker 线程命名为 MyBackgroundWorkerThread_1,第二个命名为 MyBackgroundWorkerThread_2,以此类推。

稍后当用户决定再次暂停进程时,控制不会返回到 BackgroundWorker_RunWorkerCompleted 事件处理程序中的 Wizard 线程(因为它是第一次),而是返回到某个新线程。但是,这不是致命的,用户仍然可以恢复,并且导出过程将从中断的地方继续。

但是,当我们尝试在与数据库的连接丢失的情况下启动自定义警告对话框时,就会出现问题。显然,如果向导无法与数据库通信,它就无法执行其主要任务。如果我们在一个或多个暂停/恢复周期后启动此对话框,则会引发异常并显示消息“调用线程必须是 STA,因为许多 UI 元素都需要这个”。由于这个要求,向导线程被显式设置为 STA(参见上面的相关代码),因此如果在任何暂停/恢复周期之前发生数据库连接丢失,一切正常。这个新线程显然不是 STA,因此会引发异常。

我尝试的一个选项是测试是否在我们想要启动我们的 DatabaseConnectivityLoss 对话框的时间点我们在向导线程上。由于 Wizard 线程是一个显式命名的线程(见上面的代码),我只是测试一下当前线程的 name 属性是否为 null:

在没有前面提到的异常的情况下,这可以很好地启动对话框,但是当我们在连接恢复后尝试恢复导出过程时,应用程序会挂起。

我尝试的第二件事是设置一个 SynchronizationContext 变量来保存对向导线程的引用。我的理解是,我可以使用此引用在向导线程上启动我的 DatabaseConnectivityLoss 对话框,而不管哪个线程在任何时候都是当前​​的。为此,我在向导的构造函数中设置了这个变量:

但是,当我后来尝试使用此 SynchronizationContext 将我的代码强制返回到向导线程时,它失败了:

Thread.CurrentThread.Name 通常返回 null,在其他情况下返回“NewStaThread”。我不想暗示这种行为是间歇性的。只是我尝试了许多不同的变体,并在不同的情况下从许多不同的位置调用了此方法。

我的印象是,synchronizationContext 应该持有对 Wizard 线程的引用,当我调用 Send 方法时,回调方法应该在 Wizard 线程上执行。

任何人都可以看到我的哪些假设是无效的,或者提出解决方案的途径。

从概念上讲,我认为要么我必须强制我的应用程序从 DoWork 处理程序返回到向导线程,要么在启动我的 DatabaseConnectivityLoss 对话框之前强制它返回到向导线程。据我了解,我无法访问匿名线程,直到将其设置为 STA 为时已晚,这必须在它开始之前完成。

0 投票
1 回答
6898 浏览

c# - async/await 与 ConfigureAwait 的 continueOnCapturedContext 参数和用于异步延续的 SynchronizationContext

我想先放代码,然后解释情况并据此提出我的问题:

这是一个相当简单的 WPF 示例,它在 .NET 4.5 上运行,可能没有多大意义,但这应该有助于我解释我的情况。

我在屏幕上有一个按钮,它有一个异步点击事件。查看GetValuesAsync代码时,您会看到await两次关键字的用法。第一次使用时,我将方法的continueOnCapturedContext参数设置为. 所以,这表明我不一定希望我的延续在. 到目前为止,一切都很好。Task.ConfigureAwaitfalseSynchronizationContext.Current

在第二次await使用(使用GetStringAsync方法)时,我没有调用该ConfigureAwait方法。所以,我基本上表示我回到当前的同步上下文以继续该GetStringAsync方法。因此,如您所见,我尝试TextBlock.Text在延续中设置(属于 UI 线程)属性。

当我运行应用程序并单击按钮时,我得到一个异常,给我以下消息:

调用线程无法访问此对象,因为不同的线程拥有它。

起初,这对我来说毫无意义,我认为我发现了一个错误,但后来,我意识到它GetStringAsync可能会在另一个不同于 UI 线程并且不知道同步上下文的线程中执行(很可能),因为continueOnCapturedContext设置falseTaskhttpClient.GetAsync方法返回的。

这是这里的情况吗?此外,在这种情况下,是否有机GetStringAsync会将方法发布回 UI 线程,因为 httpClient.GetAsync 方法的延续可能在 UI 线程内执行?

我在代码中也有一些评论。鉴于我的问题和代码中的评论,我在这里遗漏了什么吗?

0 投票
1 回答
525 浏览

c# - 如何仅在客户端应用程序中使用 SynchronizationContext

在我的库中,我使用SynchronizationContext使我能够轻松地在 GUI 线程上引发事件,无论该库是在 Windows 窗体还是 WPF 应用程序中使用。如果我的类是在后台线程上创建的,则 SynchronizationContext 为空,因此我直接引发事件。

例如:

这工作正常,除了我有用户报告它在 ASP.NET 应用程序中出错:

我曾假设这SynchronizationContext在 ASP.NET 网站中为空。如果 SynchronizationContext 是 AspNetSynchronizationContext 的一个实例,我需要一种不使用它的方法,尽管这样做会很麻烦,因为我没有引用 System.Web,而且它也不是公开可见的类型。

我的问题是,确定我是否在具有 GUI(例如 WinForms、WPF、WinRT)的应用程序中并且仅在该设置中使用 SynchronizationContext 的最佳方法是什么?

0 投票
1 回答
1488 浏览

c# - 是否可以使用同步上下文返回一个值 .send

我们需要使用 SynchronizationContext 通过 Send 返回一个值(特别是 MessageBox DialogResult)(我们不希望通过“Post”进行异步)。只是不确定语法。我们遇到了 MessageBox 出现在主窗口后面的问题,这被认为是由于无法轻松访问主窗体 IWin32Window 值引起的……我们正在使用它,但老实说我对此感到不舒服。