引用参数和异步任务

问题描述 投票:0回答:1

首先我了解到,异步任务中禁止使用ref、in、out参数。 然而,由于我有这个需求,我正在努力寻找最干净、最简单、最有效的解决方案。 我无意中创建了一个似乎有效的案例(我后来意识到)。但我需要您的帮助来更好地理解为什么这种情况比简单的字符串有效。 我使用 C# / WPF,我正在尝试应用 MVVM 模式。

这是从 ViewModel 调用的

await _NetworkUtil.ExecuteNetworkTask(NetworkStep1,NetworkStep2, DomainFQDN, 1000, 4, Gateway, IPAddress, SubNetMask, DNSSrvIPAddress, DomainController);

这是从实用程序类调用的方法

public async Task ExecuteNetworkTask(Result networkStep1, Result networkStep2, string domaineFqdn, int timeout, int nbPing,string gateway, string ipAddress, string subnetMask, string dnsSrvIPAddress, string domainController)

我需要更新参数NetworkStep1、NetworkStep2、DomainController 现在介绍一些重要的细节。 “结果”networkStep1 / networkStep2 是自定义类

    public class Result
{
    private bool _success;
    public bool Success {
        get { return _success; } 
        set { _success = value; } }

    private StringBuilder _message;
    public StringBuilder Message
    {
        get { return _message; }
        set
        {
            _message = value;
           
        }
    }

    private StringBuilder _exception;
    public StringBuilder Exception
    {
        get { return _exception; }
        set
        {
            _exception = value;

        }
    }

    public Result()
    {
        _message = new StringBuilder();
        Exception = new StringBuilder();
    }

    public void UpdateLog(string message)
    {
        Message.AppendLine(message);
        OnLogUpdated(message);
    }

    public void UpdateEx(string message)
    {
        Exception.AppendLine(message);
        OnLogUpdated(message);
    }

    public event Action<string> LogUpdated;
    protected virtual void OnLogUpdated(string updatedLog)
    {
        LogUpdated?.Invoke(updatedLog);
    }
}

这是在调用任务之前初始化结果的方式(在 ViewModel 中)

NetworkStep1 = new Result();
NetworkStep1.LogUpdated += UpdateTextBoxLog;
NetworkStep2 = new Result();
NetworkStep2.LogUpdated += UpdateTextBoxLog;

await _NetworkUtil.ExecuteNetworkTask(NetworkStep1,NetworkStep2, DomainFQDN, 1000, 4, Gateway, IPAddress, SubNetMask, DNSSrvIPAddress, DomainController);

.LogUpdated += UpdateTextBoxLog 用于在 Result 更新时实时更新日志窗口。 ExecuteNetworkTask 中的示例:

networkStep1.UpdateLog(‘Connected to network’)

这些是 ViewModel 中 NetworkStep1/2 的声明。 “Session”是 M_Session 模型的实例。

    public Result NetworkStep1
    {
        get { return Session.NetworkEtape1; }
        set
        {
            Session.NetworkEtape1 = value;
            OnPropertyChanged(nameof(NetworkStep1));
        }
    }

public string DomainController
{
    get { return Session.DomainController; }
    set
    {
        Session.DomainController = value;
        OnPropertyChanged(nameof(DomainController));
    }
}

总结就是这样,希望不会太混乱,同时又足够完整。 现在总结一下,我需要通过 ExecuteNetworkTask 异步任务更新 ViewModel 的 DomainControler 属性。当然,我可以将其设置为返回,但由于我可能有多个属性需要更新,因此我认为将它们设置为参数会更实用。由于 DomainController 更新不起作用,我终于意识到我无法在异步任务中使用 REF。 但是......令人惊讶的是结果类 networkStep1 和 2 更新得很好!由于日志是实时更新的,并且继续控制效果很好。

if(NetworkStep1.Success && NetworkStep2.Success)
{
    CurrentStepView = new UserAuthentification();
}

基本上,我根本没有为此目的创建 Result 类,但是我使用它的方式,似乎(除非这是一个很大的幻觉)我使用它的方式允许它在一个异步任务。 你能帮我理解一下吗?这样我就可以更新域控制器。 谢谢大家的帮助

c# asynchronous mvvm task ref
1个回答
0
投票

Result
类正在更新而
DomainController
没有更新的原因是因为
Result
是标准引用类型,而
DomainController
string
,即不可变

标准引用类型将对指定参数值的引用传递给方法,而值类型(结构和基元类型)将对指定参数值的副本传递给方法。这意味着,如果您将类传递给方法并对其进行编辑,则原始类将被更新,但如果您将整数传递给方法并更新它,则原始整数将不会更新。

字符串是不可变的引用类型,因此会将指定值的引用传递给方法,但是当编辑值时,原始值不会更改,但会创建一个新实例。

因此,对于要更新其原始实例的任何字符串参数,您需要

ref
关键字,但对于要更新其原始实例的任何类参数(例如
Result
)则不需要它。

有关引用类型与值类型的更多信息,请参阅以下资源。

© www.soinside.com 2019 - 2024. All rights reserved.