如果我将一个控件绑定到另一个控件,并且其中一个控件死亡,那么绑定会发生什么情况?

发布于 2024-12-01 09:36:17 字数 304 浏览 1 评论 0原文

例如,让我们采用编程绑定:

Binding binding = new Binding("MyProperty");
binding.Converter = new BooleanToVisibilityConverter();
binding.Source = myWindow.myObject

myButton.SetBinding(Button.VisibilityProperty, binding);

如果 myWindow 死亡并被垃圾收集,会发生什么...我是否也负责释放绑定,或者它自己知道如何执行此操作?

for example, let's take a programmatic binding:

Binding binding = new Binding("MyProperty");
binding.Converter = new BooleanToVisibilityConverter();
binding.Source = myWindow.myObject

myButton.SetBinding(Button.VisibilityProperty, binding);

What happens if myWindow dies and gets garbage collected... am I responsible for freeing up the binding as well, or does it know how to do that itself?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

羁〃客ぐ 2024-12-08 09:36:17

对于绑定来说情况并非如此,即使您使用 Source 作为 Binding,也不会出现内存泄漏。

要验证这一点,

  • 请在 Xaml 中创建一个 StackPanel、一个 TextBox (tb1) 和两个 Buttons
  • 在后面的代码中创建一个新的 TextBox< /code> (tb2)
  • 在 tb1 上设置一个 Binding,并将 Source 设置为 tb2
  • 在 tb2 上创建一个 WeakReference(这不应该如果有泄漏,则进行 GC)
  • 将 tb2 添加到 StackPanel
  • 运行程序并验证绑定是否有效
  • 单击“删除”
  • 单击“是否还活着?”

它返回 false,源 TextBox (tb2) 已被垃圾收集,因此我们没有内存泄漏

编辑:您还可以移动第一个 TextBox< 的创建/code> 从 Xaml 到代码隐藏并使用两个 WeakReferences (每个 TextBox 一个)并验证两个 textBox 是否正确进行 GC,您将看到这是真的。

Xaml

<StackPanel Name="stackPanel">
    <TextBox Name="textBox"/>
    <Button Name="removeButton" Content="Remove" Click="removeButton_Click"/>
    <Button Name="isAliveButton" Content="Is Alive?" Click="isAliveButton_Click"/>
</StackPanel>

代码隐藏

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
        TextBox toBeGCdTextBox = new TextBox();
        stackPanel.Children.Add(toBeGCdTextBox);
        Binding textBinding = new Binding
        {
            Path = new PropertyPath("Text"),
            Source = toBeGCdTextBox
        };
        textBox.SetBinding(TextBox.TextProperty, textBinding);
        _weak = new WeakReference(toBeGCdTextBox);
    }
    private WeakReference _weak;
    private void isAliveButton_Click(object sender, RoutedEventArgs e)
    {
        GC.Collect();
        MessageBox.Show(_weak.IsAlive.ToString());
    }

    private void removeButton_Click(object sender, RoutedEventArgs e)
    {
        Debug.Assert(_weak.Target == stackPanel.Children[3]);
        stackPanel.Children.Remove(stackPanel.Children[3]);
    }
}

This is not true for Bindings, you'll have no memory leak even if you use Source for the Binding.

To verify this

  • Create a StackPanel, a TextBox (tb1) and two Buttons in Xaml
  • In code behind you create a new TextBox (tb2)
  • Set a Binding on tb1 with Source set to tb2
  • Create a WeakReference on tb2 (which shouldn't be GC'd if we have a leak)
  • Add tb2 to the StackPanel
  • Run the program and verify that the binding works
  • Click Remove
  • Click Is Alive?

It returns false, the source TextBox (tb2) has been garbage collected so we have no memory leak

Edit: You can also move the creation of the first TextBox from Xaml to code behind and use two WeakReferences (one for each TextBox) and verify that both textBoxes get GC'd properly and you'll see that this is true.

Xaml

<StackPanel Name="stackPanel">
    <TextBox Name="textBox"/>
    <Button Name="removeButton" Content="Remove" Click="removeButton_Click"/>
    <Button Name="isAliveButton" Content="Is Alive?" Click="isAliveButton_Click"/>
</StackPanel>

Code Behind

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
        TextBox toBeGCdTextBox = new TextBox();
        stackPanel.Children.Add(toBeGCdTextBox);
        Binding textBinding = new Binding
        {
            Path = new PropertyPath("Text"),
            Source = toBeGCdTextBox
        };
        textBox.SetBinding(TextBox.TextProperty, textBinding);
        _weak = new WeakReference(toBeGCdTextBox);
    }
    private WeakReference _weak;
    private void isAliveButton_Click(object sender, RoutedEventArgs e)
    {
        GC.Collect();
        MessageBox.Show(_weak.IsAlive.ToString());
    }

    private void removeButton_Click(object sender, RoutedEventArgs e)
    {
        Debug.Assert(_weak.Target == stackPanel.Children[3]);
        stackPanel.Children.Remove(stackPanel.Children[3]);
    }
}
与往事干杯 2024-12-08 09:36:17

我认为它不会被垃圾收集,因为

该对象一直处于活动状态,直到垃圾收集器发现该对象
无法再通过路径从强根引用访问对象
强有力的参考

这里管理对象生命周期

你仍然有一个指针绑定。**源** 到它。

I think that it will not be garbage collected, as

The object is alive until the garbage collector finds out that the
object is no longer reachable from a strong root reference via a path
of strong references

from here Managing object lifetime

you still have a pointer binding.**Source** to it.

↙厌世 2024-12-08 09:36:17

根据 MSDN :

在 C# 中,垃圾回收由comm语言运行时处理
(CLR)这类似于Java的JVM。定期收集垃圾
检查内存堆中是否有任何未引用对象,并且
释放这些对象所持有的资源。

因此,在您的示例中,myWindow 对象无法被垃圾收集,因为存在从绑定对象到 myWindow 的引用。

According to MSDN :

In C# garbage collection is handled by the comman language runtime
(CLR) which is similar the Java's JVM. Garbage collecter periodically
checks the memory heap for any unreferenced objects, and
releases the resources held by these objects.

Therefore, in your example myWindow object cannot be garbage collected since there is a reference from binding object to myWindow.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文