C# 这会导致C中的内存泄漏吗#

C# 这会导致C中的内存泄漏吗#,c#,C#,经过多年的学习,我又开始学习C#了。我在2.0时代做过C#编程。这门语言确实已经进化了,它的奇妙之处就在于它。也就是说,我正在制作一个W8/WP8通用应用程序。基本上,当应用程序启动时,构造函数运行一个方法。此方法检查连接,如果连接已启用,则程序向前流动 private async void UpdateInformationSection(IUICommand command) { InformationModel GeneralInformationModel = new Infor

经过多年的学习,我又开始学习C#了。我在2.0时代做过C#编程。这门语言确实已经进化了,它的奇妙之处就在于它。也就是说,我正在制作一个W8/WP8通用应用程序。基本上,当应用程序启动时,构造函数运行一个方法。此方法检查连接,如果连接已启用,则程序向前流动

private async void UpdateInformationSection(IUICommand command) {
    InformationModel GeneralInformationModel = new InformationModel
    {
        apistatus = await voip_service.isAPIEnabled(),
        apimessage = await voip_service.GetAPIMessage(),
        currentbalance = await voip_service.getBalance(),
        currentip = await voip_service.getIP()
    };

    if (GeneralInformationModel.apistatus == false) {
        var msgdialog = new MessageDialog(
            "Please go to voip.ms to enable your API. You will need to know the IP address of the device on which this application is installed",
            "API connection could not be established");
        // Add commands and set their callbacks; both buttons use the same callback function instead of inline event handlers

        msgdialog.Commands.Add(new UICommand(
            "Try again", new UICommandInvokedHandler(this.UpdateInformationSection)));

        // Show the message dialog
        await msgdialog.ShowAsync();
    }

    // set the data context for the first section of the hub
    // so we can use bindings.
    mainpagehub.Sections[0].DataContext = GeneralInformationModel;
因此,如果您注意到,如果连接失败,我们会弹出一个消息对话框。弹出窗口中有一个“重试”按钮。当用户点击这个按钮时,它有一个与之相关联的“回调函数”(对我来说是新东西,我想它就像一个事件处理程序?)。无论如何,我没有编写一个新方法,而是将回调方法与messagebox在其中执行的当前方法相同。所以基本上我做的是添加了一个参数,所以我有了这个
UpdateInformationSection(IUICommand命令)
。然后回调函数也是同样的方法

我害怕的是:每次他们点击“重试”按钮,它会破坏它的旧实例吗?换句话说,当他们单击“重试”按钮时,方法是否完成执行?否则,我会想象一个场景,在这个场景中,一次又一次地调用这个方法,而每个方法都陷入了困境(如果这有意义的话)

另外,在我的构造函数中,当第一次调用该方法时,我必须将其更改为

//Update HUB Sections.            
// send null as argument since its not coming from a "command button"
// the argument is required when the API connection cant be established
// and thus a modal dialog comes up with a "try again" command button.
UpdateInformationSection(null);    

向“command”参数发送这样的“null”可以吗?这里的正确过程是什么。

当然,这里没有真正的递归,因为您使用的是
async
。但是有可能(事实上,很可能,但我没有仔细检查)在您自己的命令委托完成之前,
MessageDialog
不会完成
showsync()
方法调用。这将导致
MessageDialog
的多个实例保持可访问状态,直到您最终不显示它,从而防止它们被垃圾收集(即,最接近托管对象的真实内存泄漏)

IMHO,如果您避免了这种潜在的重新进入,那么该方法将得到更好的实现,方法是将该方法再次排队执行,而不是直接调用它。可能看起来像这样:

private async void UpdateInformationSection(IUICommand command) {
    InformationModel GeneralInformationModel = new InformationModel
{
    apistatus = await voip_service.isAPIEnabled(),
    apimessage = await voip_service.GetAPIMessage(),
    currentbalance = await voip_service.getBalance(),
    currentip = await voip_service.getIP()
};

if (GeneralInformationModel.apistatus == false) {
    var msgdialog = new MessageDialog(
        "Please go to voip.ms to enable your API. You will need to know the IP address of the device on which this application is installed",
        "API connection could not be established");
    // Add commands and set their callbacks; both buttons use the same callback function instead of inline event handlers

    msgdialog.Commands.Add(new UICommand("Try again"));

    // Show the message dialog
    await msgdialog.ShowAsync();

    var _ = CoreWindow.GetForCurrentThread().Dispatcher
        .RunAsync(CoreDispatcherPriority.Normal,
            () => { var ignoreTask = UpdateInformationSection(command); });
    return;
}

// set the data context for the first section of the hub
// so we can use bindings.
mainpagehub.Sections[0].DataContext = GeneralInformationModel;
这样,每次显示
消息对话框
时,它都有机会在重新显示之前继续并关闭

以上假设“重试”确实是您提供的唯一选项。当然,如果您有其他选项,可以使用UICommand对象来区分所选选项并执行适当的操作;“重试”将再次执行上面对
RunAsync()
方法的调用,而其他选项将执行它们所做的任何操作

尽管如此,我个人认为最好避免这种模式。据推测,用户做了一些最初启动此对话框的其他事情。至少,应该有一个“取消”选项作为“重试”的替代选项。实际上,最好是将其作为一个带有默认“Close”的警报显示,这样用户就可以简单地返回到他们所在的位置,这样在他们解决配置问题后,他们就可以再次显式地尝试操作了

我当然对这个项目做了一些假设。由于缺乏具体的细节,我承认可能有一些令人信服的理由让你现在这样做。但至少要确保这是最好的方法。让用户陷入一个可能无休止的循环对我来说似乎有点“不合适”。)

编辑:

要详细说明这段代码,请执行以下操作:

    var _ = CoreWindow.GetForCurrentThread().Dispatcher
        .RunAsync(CoreDispatcherPriority.Normal,
            () => { var ignoreTask = UpdateInformationSection(command); });
RunAsync()
方法使给定的委托在
Dispatcher
的线程(即程序的UI线程)中执行。这就是该方法已经(大概)运行的地方,因为它是由某个UI对象调用的命令。通过这种方式可以重新调用该方法,但要以非重新进入的方式。即,允许当前方法调用在下一个方法调用开始之前完成并返回。这消除了任何递归方面

被调用的委托本身-
()=>{var ignoreTask=UpdateInformationSection(command);}
-使用语句体lambda语法,只是再次调用命令方法的方法调用


最后,
RunAsync()
方法和您的命令方法都是
async
方法,返回一个
Task
实例。在这种特殊情况下,我们不需要等待它们完成,因此没有
wait
,但如果我们不使用返回值执行某些操作,编译器将生成警告。对我来说,抑制警告的最简单、最干净的方法是继续并将
任务
引用复制到一个局部变量,这足以让编译器满意。
RunAsync()
方法被复制到一个名为
的变量中,这是我通常用于我实际上不需要使用的变量,而命令方法的返回值被复制到一个名为
ignoreTask
的变量中,该变量的命名方式明确了变量的用途(即忽略从命令方法返回的
任务
).

您在方法中从不使用
命令
变量。您可以传递任何您想要的内容,而您的代码将无法分辨差异。是的。但是回调函数需要这样的函数签名。这可能解决了您的第二个问题。对于第一个问题,我不确定您担心什么。如果y你对递归调用这个函数感觉很好,没什么好担心的。啊,是的,这就是我要找的词。递归。所以,是的,每次他们单击“重试”,这个方法都会被一次又一次调用,但在某个点上,它会“重新冒泡”吗到原始方法并杀死messagebox的所有实例?是的,函数返回s