标签: synchronizationcontext

从给定的线程获取SynchronizationContext

我似乎没有找到如何获得SynchronizationContext给定的Thread:

Thread uiThread = UIConfiguration.UIThread;
SynchronizationContext context = uiThread.Huh?;
Run Code Online (Sandbox Code Playgroud)

我为什么需要那个?

因为我需要从前端应用程序的不同位置发布到UIThread.所以我在一个名为的类中定义了一个静态属性UIConfiguration.我在Program.Main方法中设置了这个属性:

UIConfiguration.UIThread = Thread.CurrentThread;
Run Code Online (Sandbox Code Playgroud)

在那一刻我可以肯定我有正确的线程,但是我不能设置像这样的静态属性

UIConfiguration.SynchronizationContext = SynchronizationContext.Current
Run Code Online (Sandbox Code Playgroud)

因为尚未安装该类的WinForms实现.由于每个线程都有自己的SynchronizationContext,因此必须可以从给定Thread对象中检索它,或者我完全错了?

c# multithreading .net-3.5 synchronizationcontext

7
推荐指数
3
解决办法
1万
查看次数

SynchronizationContext,它何时流动,何时不流动?

我正在努力学习SynchronizationContext和朋友们.如果我在例如控制台应用程序的开头设置自定义同步上下文.在什么条件下,当前的同步上下文会与我的异步操作一起流动?Task和其他人之间是否存在差异,例如Delegate.BeginInvoke

void Main()
{
    SynchronizationContext.SetSynchronizationContext(new FooContext());
    Action a = () =>
    {
         var current = SynchronizationContext.Current;
         //current is null here
    };
    a.BeginInvoke(null,null);

    ...sleep
Run Code Online (Sandbox Code Playgroud)

如果我在线程池上执行东西,我是否被迫为当前正在执行我的工作的特定线程分配同步上下文?

c# asynchronous synchronizationcontext task-parallel-library

6
推荐指数
1
解决办法
776
查看次数

如何修复具有SynchronizationContext的线程池线程的死锁?

我在使用HttpClient发送http请求时遇到间歇性死锁,有时它们永远不会返回到await SendAsync我的代码中.我能够找出处理内部请求的线程HttpClient/ HttpClientHandler由于某种原因SynchronizationContext它在死锁期间有一个.我想弄清楚如何使用线程最终得到a SynchronizationContext,通常他们没有.我会假设无论什么对象导致SynchronizationContext设置它也会阻塞Thread,这会导致死锁.

我是否能够在TPL ETW事件中看到任何相关内容?

我该如何解决这个问题?



编辑2: 我注意到这些死锁的地方是在ServiceContractwindows服务中的wcf (参见下面的代码)中.该SynchronizationContext所导致的问题实际上是一个是WindowsFormsSynchronizationContext,我以为是一些控制入门创建并造成没有清理正确(或者类似).我意识到几乎可以肯定不应该在Windows服务中发生任何Windows窗体的事情,我并不是说我同意它是如何使用的.但是,我没有使用它编写任何代码,我不能轻易地改变所有的引用.

编辑:这是我遇到问题的wcf服务的一般概念的一个例子.这是一个简化版本,而不是确切的代码:

[ServiceContract]
[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single, ConcurrencyMode = ConcurrencyMode.Multiple)]
internal class SampleWcfService
{
    private readonly HttpMessageInvoker _invoker;

    public SampleWcfService(HttpMessageInvoker invoker)
    {
        _invoker = invoker;
    }

    [WebGet(UriTemplate = "*")]
    [OperationContract(AsyncPattern = true)]
    public async Task<Message> GetAsync()
    {
        var context = WebOperationContext.Current;
        using (var request = CreateNewRequestFromContext(context))
        {
            var response = await …
Run Code Online (Sandbox Code Playgroud)

.net c# synchronizationcontext task-parallel-library async-await

6
推荐指数
1
解决办法
518
查看次数

为什么在Console App中没有捕获默认的SynchronizationContext?

我正在尝试更多地了解它SynchronizationContext,所以我制作了这个简单的控制台应用程序:

private static void Main()
{
    var sc = new SynchronizationContext();
    SynchronizationContext.SetSynchronizationContext(sc);
    DoSomething().Wait();
}

private static async Task DoSomething()
{
    Console.WriteLine(SynchronizationContext.Current != null); // true
    await Task.Delay(3000);
    Console.WriteLine(SynchronizationContext.Current != null); // false! why ?
}
Run Code Online (Sandbox Code Playgroud)

如果我理解正确,await操作员会捕获当前的信息SynchronizationContext然后将其余的异步方法发布到它.

但是,在我的应用程序中,之后SynchronizationContext.Current为null await.这是为什么 ?

编辑:

即使我自己使用SynchronizationContext它也不会被捕获,尽管它的Post功能被调用.这是我的SC:

public class MySC : SynchronizationContext
{
    public override void Post(SendOrPostCallback d, object state)
    {
        base.Post(d, state);
        Console.WriteLine("Posted");
    }
}
Run Code Online (Sandbox Code Playgroud)

这就是我使用它的方式:

var sc = new MySC();
SynchronizationContext.SetSynchronizationContext(sc); …
Run Code Online (Sandbox Code Playgroud)

c# console-application synchronizationcontext async-await

6
推荐指数
1
解决办法
515
查看次数

当线程返回到线程池时,SynchronizationContext.Current是否重置

假设我有这个代码

ThreadPool.QueueUserWorkItem(unused => 
    {
        SynchronizationContext.SetSynchronizationContext(
            new MyCustomSynchronizationContext());

        // not reset back to null
    }, null);
Run Code Online (Sandbox Code Playgroud)

当前同步上下文泄漏回线程池.如果有人再次调用ThreadPool.QueueUserWorkItem并且同一个线程用于处理其他工作项,那么该线程的当前同步上下文是否会重置为null或者它是否会保留MyCustomSynchronizationContext?

相同的答案是否适用于在线程池上执行任务的任何其他方式,例如Task.Run,​​BeginInvoke等?

我知道一般来说TLS没有重置,但是.NET源代码显示当前同步上下文的存储没有非常明确地定义(大多数时候它来自executioncontext但是它似乎特别适用于WinRT的一些原因).

c# asynchronous synchronizationcontext threadpool async-await

5
推荐指数
1
解决办法
373
查看次数

SynchronizationContext在Task.Run上流动,但不在await上流动

在阅读了Stephen Toub关于SynchronizationContext的文章后,我留下了一个关于这段.NET 4.5代码输出的问题:

private void btnDoSomething_Click()
{
    LogSyncContext("btnDoSomething_Click");
    DoItAsync().Wait();
}
private async Task DoItAsync()
{
    LogSyncContext("DoItAsync");
    await PerformServiceCall().ConfigureAwait(false); //to avoid deadlocking
}
private async Task PerformServiceCall()
{
    LogSyncContext("PerformServiceCall 1");
    HttpResponseMessage message = await new HttpClient
    {
        BaseAddress = new Uri("http://my-service")
    }
    .GetAsync("/").ConfigureAwait(false); //to avoid deadlocking
    LogSyncContext("PerformServiceCall 2");
    await ProcessMessage(message);
    LogSyncContext("PerformServiceCall 3");
}

private async Task ProcessMessage(HttpResponseMessage message)
{
    LogSyncContext("ProcessMessage");
    string data = await message.Content.ReadAsStringAsync();
    //do something with data
}

private static void LogSyncContext(string statementId)
{
    Trace.WriteLine(String.Format("{0} {1}", statementId, …
Run Code Online (Sandbox Code Playgroud)

.net c# synchronizationcontext async-await

5
推荐指数
1
解决办法
1978
查看次数

当前的SynchronizationContext可以为null吗?

https://msdn.microsoft.com/en-us/magazine/gg598924.aspx

这是一篇很棒的文章,我知道所有细节都无法涵盖,因为这实际上涉及粘贴.NET框架的源代码.所以引用文字:

每个线程都有一个当前上下文.如果"Current"为null,则按照惯例,线程的当前上下文为"new SynchronizationContext()".

但另一方面:

默认情况下,当前的SynchronizationContext是在await点捕获的,并且此SynchronizationContext用于在await之后恢复(更确切地说,它捕获当前的SynchronizationContext, 除非它为null,在这种情况下它捕获当前的TaskScheduler)

这两个陈述相互矛盾,所以我认为这是作者做出的一些简化的结果(我很好).

有人能解释一下吗?代码可能有助于回答我的问题(查找syncCtx变量),这段代码与第二个引用相关.

c# multithreading synchronizationcontext

5
推荐指数
1
解决办法
632
查看次数

ConfigureAwait(false)导致错误而不是死锁的情况

假设我编写了一个依赖于async方法的库:

namespace MyLibrary1
{
    public class ClassFromMyLibrary1
    {
        public async Task<string> MethodFromMyLibrary1(string key, Func<string, Task<string>> actionToProcessNewValue)
        {
            var remoteValue = await GetValueByKey(key).ConfigureAwait(false);

            //do some transformations of the value
            var newValue = string.Format("Remote-{0}", remoteValue);

            var processedValue = await actionToProcessNewValue(newValue).ConfigureAwait(false);

            return string.Format("Processed-{0}", processedValue);
        }

        private async Task<string> GetValueByKey(string key)
        {
            //simulate time-consuming operation
            await Task.Delay(500).ConfigureAwait(false);

            return string.Format("ValueFromRemoteLocationBy{0}", key);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

我遵循了在我的图书馆里到处使用ConfigureAwait(false)(就像在这篇文章中)的建议.然后我从我的测试应用程序以同步方式使用它并获得失败:

namespace WpfApplication1
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary> …
Run Code Online (Sandbox Code Playgroud)

.net c# synchronizationcontext async-await

5
推荐指数
1
解决办法
1151
查看次数

如何解释等待/异步同步上下文切换行为

我对以下代码的行为有几件事情(但有一件主要事情)不了解。

有人可以帮忙解释一下吗?

它实际上是非常简单的代码-只是一个常规方法调用异步方法。在异步方法中,我使用using块尝试临时更改SynchronizationContext。

在代码的不同点,我探查了当前的SynchronizationContext。

这是我的问题:

  1. 当执行到达位置“ 2.1”时,上下文已更改为上下文2。好的。然后,因为我们点击了一个“ await”,任务被返回,执行跳回到位置“ 1.2”。为什么然后在位置1.2处上下文不“粘在”上下文2上?

    也许using语句和异步方法正在发生一些魔术?
  2. 在位置2.2,为什么上下文不是上下文#2?上下文是否不应该延续到“继续”(“ await”之后的语句)中?

码:

    public class Test
    {
        public void StartHere()
        {
            SynchronizationContext.SetSynchronizationContext(new SynchronizationContext());

            this.logCurrentSyncContext("1.1"); // Context #1
            Task t = f();
            this.logCurrentSyncContext("1.2"); // Context #1, why not Context #2?
            t.Wait();
            this.logCurrentSyncContext("1.3"); // Context #1
        }


        private async Task f()
        {
            using (new ThreadPoolSynchronizationContextBlock())
            {
                this.logCurrentSyncContext("2.1");  // Context #2
                await Task.Delay(7000);
                this.logCurrentSyncContext("2.2");  // Context is NULL, why not Context #2?
            }

            this.logCurrentSyncContext("2.3");  // Context #1
        }


        // Just show the current …
Run Code Online (Sandbox Code Playgroud)

.net c# using synchronizationcontext async-await

5
推荐指数
1
解决办法
1222
查看次数

在ASP.NET的上下文中,为什么不调用异步方法时Task.Run(...).结果死锁?

我用一个控制器和一个方法创建了一个简单的WebApi项目:

public static class DoIt
{
    public static async Task<string> GetStrAsync(Uri uri)
    {
        using (var client = new HttpClient())
        {
            var str = await client.GetStringAsync(uri);
            return str;
        }
    }
}

public class TaskRunResultController : ApiController
{
    public string Get()
    {
        var task = Task.Run(() =>
            DoIt.GetStrAsync(new Uri("http://google.com"))
        );
        var result = task.Result;

        return result;
    }
}
Run Code Online (Sandbox Code Playgroud)

我非常了解async/await和tasks; 斯蒂芬克莱里几乎虔诚地跟随他.只是存在.Result让我焦虑,我希望这会陷入僵局.我知道这Task.Run(...)很浪费,导致在等待异步DoIt()完成时占用一个线程.

问题是这不是死锁,而是让我心悸.

我看到一些答案,如/sf/answers/2282496401/,我也观察到SynchronizationContext.Currentlambda执行时为null.但是,我也有类似的问题,问为什么上面的代码会出现死锁,而且我发现死锁ConfigureAwait(false)是在使用(不捕获上下文)的情况下发生的.Result.

是什么赋予了?

c# asp.net asynchronous task synchronizationcontext

5
推荐指数
1
解决办法
1064
查看次数