AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • Início
  • system&network
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • Início
  • system&network
    • Recentes
    • Highest score
    • tags
  • Ubuntu
    • Recentes
    • Highest score
    • tags
  • Unix
    • Recentes
    • tags
  • DBA
    • Recentes
    • tags
  • Computer
    • Recentes
    • tags
  • Coding
    • Recentes
    • tags
Início / user-19765410

GorillasPaw's questions

Martin Hope
user
Asked: 2025-04-25 13:18:16 +0800 CST

Um método inline pode causar uma condição de corrida para um objeto referenciado pelo tipo de referência?

  • 5

Tenho uma variável de instância ou propriedade chamada Settingque é compartilhada entre threads.
Uma nova instância ocasionalmente será atribuída a essa variável por outras threads.
O método que usa Settingcopiará a referência antes de funcionar, e não há problema em usar a antiga Settingse ela estiver sendo atualizada quando o trabalho estiver prestes a começar, então o bloqueio não é necessário.

A leitura e a escrita únicas do tipo de referência são atômicas em C#, mas instruções compostas como var foo = new Foo()essa não são atômicas e podem ser reordenadas.
Este problema é bem ilustrado no bloqueio de dupla verificação. https://medium.com/@wangberlin2000/why-volatile-is-essential-in-double-checked-locking-singleton-0ba2906623fe
O link foi escrito em Java, mas o mesmo se aplica a C#.

https://csharpindepth.com/Articles/Singleton
Adicionado também o link para C#. Confira a "Terceira versão - tentativa de segurança de thread usando bloqueio de verificação dupla".

Gostaria de saber se é possível ler o Settingquando seu endereço de memória é alocado, mas a inicialização do objectnão é concluída.

O código de exemplo tem 3 Settingvariáveis ​​de membro de instância, propertye virtual propertyfunções que atualizam o Setting. É para fins de demonstração e o código real tem apenas uma Settinge uma função.

  1. É UpdateMemberAsyncseguro usar, já que o conteúdo GetSettingAsyncnão pode vazar antes ou depois da awaitreordenação da memória?
  2. Não é UpdateMemberByInlinableseguro usar porque GetSettingpode ser incorporado em vez de retornar o inicializado object?
  3. É UpdateVirtualMemberseguro usar porque virtual propertynão pode ser embutido?
  4. É UpdateMemberByNonInlinableseguro usar porque Apinão pode ser embutido?
  5. É UpdateMemberUsingBarrierseguro usar?
  6. Há algo que estou esquecendo além dos exemplos fornecidos?

Adicionado o link fornecido por Peter Cordes para aqueles que buscam informações mais detalhadas. https://preshing.com/20120612/an-introduction-to-lock-free-programming/

public class Service
{
    public Setting Setting = new();
    public Setting SettingProperty { get; set; } = new();
    public virtual Setting SettingVirtualProperty { get; set; } = new();

    // Called by other threads.
    public async Task StartAsync()
    {
        // It doesn't have to be the most recent value.
        var setting = Setting;

        await Foo(setting);
        await Bar(setting);
    }

    // Api is a class with a non-virtual or sealed function.
    public void UpdateMemberByInlinable(Api api)
    {
        Setting = api.GetSetting();

        // Inlined as below.
        var t = new Setting();

        Setting = ptrT;
        // or
        SettingProperty.BackingField = ptrT;

        // Set members of t after assigning the ptr.
    }

    // Api can be anything.
    public async Task UpdateMemberAsync(Api api)
    {
        Setting = await api.GetSettingAsync();
        // or
        SettingProperty = await api.GetSettingAsync();
        // or
        SettingVirtualProperty = await api.GetSettingAsync();
    }

    // Api can be anything.
    public void UpdateVirtualMember(Api api)
    {
        SettingVirtualProperty = api.GetSetting();
    }

    // Api is an interface or a class with a non-sealed virtual function.
    public void UpdateMemberByNonInlinable(Api api)
    {
        Setting = api.GetSetting();
        // or
        SettingProperty = api.GetSetting();
    }

    // Api can be anything.
    public void UpdateMemberUsingBarrier(Api api)
    {
        var setting = api.GetSetting();

        Thread.MemoryBarrier();

        Setting = setting;
        // or
        SettingProperty = setting;
    }
}
c#
  • 2 respostas
  • 157 Views
Martin Hope
GorillasPaw
Asked: 2024-12-26 22:19:23 +0800 CST

Semáforo causando deadlock no WPF

  • 5

DoAsync, ConnectFtpAsync, ConnectDbAsynctudo funciona no projeto Console quando o número de tarefas excede o limite do semáforo.
No entanto ConnectFtpAsynce ConnectDbAsyncexceto DoAsyncfazem com que o projeto WPF congele quando o número de tarefas excede o limite do semáforo.

ButtonPressedAsync()qual é a chamada mais externa não usa o ConfigureAwait(false)e ConfigureAwait(false)usado na chamada interna não deve importar.

Remover o ConfigureAwait(false)from inner calls não resolveu o problema.
Remover o semáforo ou não exceder o limite do semáforo resolveu o problema.

FluentFTP e Oracle são usados ​​para o código fornecido.
3 exemplos são testados separadamente.

  1. Por que ConnectFtpAsynccongelar ConnectDbAsyncum projeto WPF?
  2. Por que DoAsynco projeto WPF não congela?

    protected override async Task ExecuteAsync(CancellationToken ct)
    {
        await ButtonPressedAsync();
    }
    
    private static async Task ButtonPressedAsync()
    {
        try
        {
            var connectionLimit = 4;
            var smph = new Semaphore(connectionLimit, connectionLimit);
            var tasks = new List<Task>();
    
            for (var i = 0; i < connectionLimit + 1; ++i)
                tasks.Add(DoAsync(smph));
    
            //for (var i = 0; i < connectionLimit + 1; ++i)
            //    tasks.Add(ConnectFtpAsync(smph));
    
            //for (var i = 0; i < connectionLimit + 1; ++i)
            //    tasks.Add(ConnectDbAsync(smph));
    
            await Task.WhenAll(tasks).ConfigureAwait(false);
        }
        catch (Exception ex)
        {
            ;
        }
    }
    
    private static async Task DoAsync(Semaphore smph)
    {
        smph.WaitOne();
    
        await Task.Delay(500).ConfigureAwait(false);
    
        smph.Release();
    }
    
    private static async Task ConnectFtpAsync(Semaphore smph)
    {
        smph.WaitOne();
    
        var ftpConnection = new AsyncFtpClient(
            host: "ip",
            port: 21,
            user: "id",
            pass: "pswd");
    
        await ftpConnection.Connect().ConfigureAwait(false);
    
        smph.Release();
    }
    
    private static async Task ConnectDbAsync(Semaphore smph)
    {
        smph.WaitOne();
    
        var credential = "credential";
        using var dbConnection = new OracleConnection(credential);
        await dbConnection.OpenAsync().ConfigureAwait(false);
        await dbConnection.CloseAsync().ConfigureAwait(false);
    
        smph.Release();
    }

c#
  • 1 respostas
  • 87 Views
Martin Hope
GorillasPaw
Asked: 2024-12-05 16:07:59 +0800 CST

Fluxo de controle de tarefas recursivas

  • 2
Bloqueado por 21 horas . Há disputas sobre o conteúdo desta pergunta sendo resolvidas neste momento. Ela não está aceitando novas respostas ou interações no momento.

Quando eu descomento await Task.Delay(1_000);, foo.DoAsyncwithin Task.Runé Task.CompletedTaskporque ele espera por Task.Runoverhead. Então ele roda normalmente.

Quando eu comento await Task.Delay(1_000);, foo.DoAsyncdentro do Task.Run é ele mesmo. Após o primeiro hit do breakpoint2 no modo de depuração, ele não atinge mais o breakpoint2.

internal class Foo
{
    public Task DoAsync { get; set; }

    public void Recursive()
    {
        // Breakpoint1
        Recursive();
    }
}
var foo = new Foo() { DoAsync = Task.CompletedTask };

//foo.Recursive();

Console.WriteLine($"Outer ThreadId: {Environment.CurrentManagedThreadId}");

var task = Task.Run(async () =>
{
    Console.WriteLine($"Inner ThreadId: {Environment.CurrentManagedThreadId}");
    // Breakpoint2
    await foo.DoAsync;
    Console.WriteLine("""
        ******
        ******
        ******
        done
        ******
        ******
        ******
        """);
});

await Task.Delay(1_000);

foo.DoAsync = task;

await foo.DoAsync;

Eu esperava que ele atingisse o breakpoint2 infinitamente, assim como foo.Recursiveatingiria o breakpoint1 infinitamente até que ele travasse. Para onde vai o fluxo de controle após o acerto inicial no breakpoint2?

c#
  • 1 respostas
  • 71 Views

Sidebar

Stats

  • Perguntas 205573
  • respostas 270741
  • best respostas 135370
  • utilizador 68524
  • Highest score
  • respostas
  • Marko Smith

    Reformatar números, inserindo separadores em posições fixas

    • 6 respostas
  • Marko Smith

    Por que os conceitos do C++20 causam erros de restrição cíclica, enquanto o SFINAE antigo não?

    • 2 respostas
  • Marko Smith

    Problema com extensão desinstalada automaticamente do VScode (tema Material)

    • 2 respostas
  • Marko Smith

    Vue 3: Erro na criação "Identificador esperado, mas encontrado 'import'" [duplicado]

    • 1 respostas
  • Marko Smith

    Qual é o propósito de `enum class` com um tipo subjacente especificado, mas sem enumeradores?

    • 1 respostas
  • Marko Smith

    Como faço para corrigir um erro MODULE_NOT_FOUND para um módulo que não importei manualmente?

    • 6 respostas
  • Marko Smith

    `(expression, lvalue) = rvalue` é uma atribuição válida em C ou C++? Por que alguns compiladores aceitam/rejeitam isso?

    • 3 respostas
  • Marko Smith

    Um programa vazio que não faz nada em C++ precisa de um heap de 204 KB, mas não em C

    • 1 respostas
  • Marko Smith

    PowerBI atualmente quebrado com BigQuery: problema de driver Simba com atualização do Windows

    • 2 respostas
  • Marko Smith

    AdMob: MobileAds.initialize() - "java.lang.Integer não pode ser convertido em java.lang.String" para alguns dispositivos

    • 1 respostas
  • Martin Hope
    Fantastic Mr Fox Somente o tipo copiável não é aceito na implementação std::vector do MSVC 2025-04-23 06:40:49 +0800 CST
  • Martin Hope
    Howard Hinnant Encontre o próximo dia da semana usando o cronógrafo 2025-04-21 08:30:25 +0800 CST
  • Martin Hope
    Fedor O inicializador de membro do construtor pode incluir a inicialização de outro membro? 2025-04-15 01:01:44 +0800 CST
  • Martin Hope
    Petr Filipský Por que os conceitos do C++20 causam erros de restrição cíclica, enquanto o SFINAE antigo não? 2025-03-23 21:39:40 +0800 CST
  • Martin Hope
    Catskul O C++20 mudou para permitir a conversão de `type(&)[N]` de matriz de limites conhecidos para `type(&)[]` de matriz de limites desconhecidos? 2025-03-04 06:57:53 +0800 CST
  • Martin Hope
    Stefan Pochmann Como/por que {2,3,10} e {x,3,10} com x=2 são ordenados de forma diferente? 2025-01-13 23:24:07 +0800 CST
  • Martin Hope
    Chad Feller O ponto e vírgula agora é opcional em condicionais bash com [[ .. ]] na versão 5.2? 2024-10-21 05:50:33 +0800 CST
  • Martin Hope
    Wrench Por que um traço duplo (--) faz com que esta cláusula MariaDB seja avaliada como verdadeira? 2024-05-05 13:37:20 +0800 CST
  • Martin Hope
    Waket Zheng Por que `dict(id=1, **{'id': 2})` às vezes gera `KeyError: 'id'` em vez de um TypeError? 2024-05-04 14:19:19 +0800 CST
  • Martin Hope
    user924 AdMob: MobileAds.initialize() - "java.lang.Integer não pode ser convertido em java.lang.String" para alguns dispositivos 2024-03-20 03:12:31 +0800 CST

Hot tag

python javascript c++ c# java typescript sql reactjs html

Explore

  • Início
  • Perguntas
    • Recentes
    • Highest score
  • tag
  • help

Footer

AskOverflow.Dev

About Us

  • About Us
  • Contact Us

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve