none
高频重复调用数据转换器的时候报错啦DependencyProperty.UnsetValue!!! RRS feed

  • 问题

  • <GroupBox Header="I2C Addr (LLRR)" Grid.Row="1" Grid.RowSpan="1">
                        <Grid>
                            <Grid.RowDefinitions>
                                <RowDefinition Height="auto"/>
                                <RowDefinition Height="*"/>
                            </Grid.RowDefinitions>
                            <Button Name="StartButton" Content="Start" Grid.Row="1" Click="StartComm" VerticalAlignment="Center" HorizontalContentAlignment="Center"/>
                            <UniformGrid Grid.Row="0" Columns="4">
                                <Label Name="i2c_addr_ll" Content="0x28" HorizontalAlignment="Center">
                                    <Label.Foreground>
                                        <MultiBinding Converter="{StaticResource BrushDarkMultiConv}">
                                            <Binding Path="I2C_Active[0]" Mode="OneWay"/>
                                            <Binding Path="OwiMode[0]" Mode="OneWay"/>
                                        </MultiBinding>
                                    </Label.Foreground>
                                </Label>
                                <Label Name="i2c_addr_l" Content="0x29" HorizontalAlignment="Center">
                                    <Label.Foreground>
                                        <MultiBinding Converter="{StaticResource BrushDarkMultiConv}">
                                            <Binding Path="I2C_Active[1]" Mode="OneWay"/>
                                            <Binding Path="OwiMode[1]" Mode="OneWay"/>
                                        </MultiBinding>
                                    </Label.Foreground>
                                </Label>
                                <Label Name="i2c_addr_r" Content="0x2A" HorizontalAlignment="Center">
                                    <Label.Foreground>
                                        <MultiBinding Converter="{StaticResource BrushDarkMultiConv}">
                                            <Binding Path="I2C_Active[2]" Mode="OneWay"/>
                                            <Binding Path="OwiMode[2]" Mode="OneWay"/>
                                        </MultiBinding>
                                    </Label.Foreground>
                                </Label>
                                <Label Name="i2c_addr_rr" Content="0x2B" HorizontalAlignment="Center">
                                    <Label.Foreground>
                                        <MultiBinding Converter="{StaticResource BrushDarkMultiConv}">
                                            <Binding Path="I2C_Active[3]" Mode="OneWay"/>
                                            <Binding Path="OwiMode[3]" Mode="OneWay"/>
                                        </MultiBinding>
                                    </Label.Foreground>
                                </Label>
                            </UniformGrid>
                        </Grid>
                    </GroupBox>

    上面为xaml代码。

    public partial class MainWindow : Window, INotifyPropertyChanged
    {
    public MainWindow()
            {
                InitializeComponent();
               i2c_addr_ll.DataContext = this;
                i2c_addr_l.DataContext = this;
                i2c_addr_r.DataContext = this;
                i2c_addr_rr.DataContext = this;
            }
    
    
    public bool[] I2C_Active
            {
                get
                {
                    if (null == comm)
                        return new bool[Communication.max_i2c_addr_num] { false, false, false, false };
                    else
                        return comm.I2C_Active;
                }
            }
    }
    
    private void CommI2CActiveChangedEventCallback()
            {
                NotifyRunStateChanged("I2C_Active");
            }

    这是数据源。

    class BrushDarkMultiConverters : IMultiValueConverter
        {
            public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
            {
                Color colorRun = new Color
                {
                    R = 0x07,
                    G = 0xa1,
                    B = 0xb1,
                    A = 0xFF
                };
    
                Color colorOff = new Color
                {
                    R = 0xD3,
                    G = 0x40,
                    B = 0x87,
                    A = 0xFF
                };
    
                bool val0 = (bool)values[0];
                Byte val1 = (Byte)values[1];
    
                if (false == (bool)val0)
                    return Brushes.LightGray;
    
    #if false
                if (0 == val1)
                    return new SolidColorBrush(colorOff);
                else
                    return new SolidColorBrush(colorRun);
    #else
                return new SolidColorBrush(colorRun);
    #endif
            }

    这是转换器。

    当我进行一个重复操作的时候,这个操作会调用CommI2CActiveChangedEventCallback,则会调用转换器。

    但是转换器中会突发性的出现val[0]为DependencyProperty.UnsetValue的错误。概率未知,无法重现。整个操作过程中出现的时机也未知。


    2019年11月7日 7:26

全部回复

  • 再补一张报错的截图

    2019年11月7日 7:57
  • Hi,

    看你的代码好像没什么错,你看一下下面链接,

    https://www.cnblogs.com/walterlv/p/10236537.html

    Best Regards,

    Alex


    如果您对Visual Studio 或Microsoft Azure相关产品感兴趣,请点击此链接,或扫描以下二维码注册获取相关信息。




    2019年11月10日 11:20
    版主
  • hi Alex,

    那个链接我也看过,但是没有受到什么启发

    2019年11月11日 6:44
  • 你能举例你是如何应用的吗?

    我看了眼你的代码,大意基本是根据布尔数组和字节数组来返回颜色值?

    我没有改动你的转换器,我在xaml代码的CS页面使用了定时器,每70毫秒随机改动布尔数组和字节数组。

    持续运行约有5分钟,没有发现报错。

    我不清楚你定义的方法是有何意义,所以我删了。

    改动后的XAML页面

     <Window.Resources>
            <local:BrushDarkMultiConverters x:Key="c1"/>
        </Window.Resources>
        <Grid  >
            <GroupBox   Header="I2C Addr (LLRR)" Grid.Row="1" Grid.RowSpan="1">
                <Grid>
                    <Grid.RowDefinitions>
                        <RowDefinition Height="auto"/>
                        <RowDefinition Height="*"/>
                    </Grid.RowDefinitions>
                    <Button Name="StartButton" Content="Start" Grid.Row="1"   VerticalAlignment="Center" HorizontalContentAlignment="Center"/>
                    <UniformGrid Grid.Row="0" Columns="4">
                        <Label Name="i2c_addr_ll" Content="0x28" HorizontalAlignment="Center">
                            <Label.Foreground>
                                <MultiBinding Converter="{ StaticResource c1 }">
                                    <Binding RelativeSource="{RelativeSource Mode=FindAncestor,AncestorLevel=1,AncestorType=local:MainWindow}" Path="I2C_Active[0]"  Mode="OneWay"/>
                                    <Binding RelativeSource="{RelativeSource Mode=FindAncestor,AncestorLevel=1,AncestorType=local:MainWindow}" Path="OwiMode[0]" Mode="OneWay"/>
                                </MultiBinding>
                            </Label.Foreground>
                        </Label>
                        <Label Name="i2c_addr_l" Content="0x29" HorizontalAlignment="Center">
                            <Label.Foreground>
                                <MultiBinding Converter="{StaticResource c1 }">
                                    <Binding RelativeSource="{RelativeSource Mode=FindAncestor,AncestorLevel=1,AncestorType=local:MainWindow}" Path="I2C_Active[1]" Mode="OneWay"/>
                                    <Binding  RelativeSource="{RelativeSource Mode=FindAncestor,AncestorLevel=1,AncestorType=local:MainWindow}" Path="OwiMode[1]" Mode="OneWay"/>
                                </MultiBinding>
                            </Label.Foreground>
                        </Label>
                        <Label Name="i2c_addr_r" Content="0x2A" HorizontalAlignment="Center">
                            <Label.Foreground>
                                <MultiBinding Converter="{StaticResource  c1}">
                                    <Binding  RelativeSource="{RelativeSource Mode=FindAncestor,AncestorLevel=1,AncestorType=local:MainWindow}" Path="I2C_Active[2]" Mode="OneWay"/>
                                    <Binding  RelativeSource="{RelativeSource Mode=FindAncestor,AncestorLevel=1,AncestorType=local:MainWindow}" Path="OwiMode[2]" Mode="OneWay"/>
                                </MultiBinding>
                            </Label.Foreground>
                        </Label>
                        <Label Name="i2c_addr_rr" Content="0x2B" HorizontalAlignment="Center">
                            <Label.Foreground>
                                <MultiBinding Converter="{StaticResource c1 }">
                                    <Binding  RelativeSource="{RelativeSource Mode=FindAncestor,AncestorLevel=1,AncestorType=local:MainWindow}" Path="I2C_Active[3]" Mode="OneWay"/>
                                    <Binding  RelativeSource="{RelativeSource Mode=FindAncestor,AncestorLevel=1,AncestorType=local:MainWindow}"  Path="OwiMode[3]" Mode="OneWay"/>
                                </MultiBinding>
                            </Label.Foreground>
                        </Label>
                    </UniformGrid>
                </Grid>
            </GroupBox>
        </Grid>

    改动后的cs页面

     public partial class MainWindow : Window,INotifyPropertyChanged
        {
            DispatcherTimer timer = new DispatcherTimer();
            public MainWindow()
            {
                InitializeComponent();
                i2c = new bool[4] {false,false,false,false };
                om = new byte[] {0,1,0,1 };
                timer.Interval = TimeSpan.FromMilliseconds(70);
                timer.Start();
                timer.Tick += Timer_Tick;
            }
            Random random = new Random();
            private void Timer_Tick(object sender, EventArgs e)
            {
                this.Dispatcher.Invoke(() =>
                {
                    I2C_Active = new bool[4] {
                        random.Next() % 2 == 0 ? true : false,
                        random.Next() % 2 == 0 ? true : false ,
                        random.Next() % 2 == 0 ? true : false ,
                        random.Next() % 2 == 0 ? true : false
                    };
    
                    om = new byte[4] {
                         (byte)(random.Next() % 2 == 0 ? 1 : 0),
                         (byte)(random.Next() % 2 == 0 ? 1 : 0),
                         (byte)(random.Next() % 2 == 0 ? 1 : 0),
                         (byte)(random.Next() % 2 == 0 ? 1 : 0)
                    };
                });
               
    
            }
    
     
            public bool[] I2C_Active
            {
                get
                {
                    return i2c;
                }
                set
                {
                    i2c = value;
                    OnChanged(new PropertyChangedEventArgs("I2C_Active"));
                }
            }
            private bool[] i2c ;
            private byte[] om;
            public byte[] OwiMode
            {
                get
                {
                    return om;
                }
                set
                {
                    om = value;
                    OnChanged(new PropertyChangedEventArgs("OwiMode"));
                }
            }
            protected void OnChanged(PropertyChangedEventArgs args) => PropertyChanged?.Invoke(this, args);
            public event PropertyChangedEventHandler PropertyChanged;
        }


    • 已编辑 ARM830 2019年11月12日 7:12
    2019年11月12日 7:10
  • 那个方法就是通知值发生了变化。因为懒得手写属性,就用了自动属性,然后手动通知。

    应用的场景就是重复调用通知的那个方法,但是没有set binding的值。

    如果是因为没有set那个值,那么该现象应该是必现的。

    但是在我重复的10万次调用中,是概率性出现的。

    2019年11月13日 3:02
  • 我写的代码和你实际应用类似。

    但是你是手动通知属性改变?

    那应该是顺序有问题,造成转换器使用时绑定值为NULL。

    建议使用改变方法,重新测试

    2019年11月13日 5:00
  • 说的顺序是指什么顺序,如果是set value和Notify的顺序的话,也不会造成value为null,因为本身就有默认值。

    即使可以造成value为null,那么报错提示也不应该是UnsetValue。

    2019年11月14日 2:08
  • Hi,

    只有返回值是null的时候才会有这个报错.看一下下面的链接

    https://stackoverflow.com/questions/2811405/why-do-i-get-a-dependencyproperty-unsetvalue-when-converting-a-value-in-a-multib

    Best Regards,

    Alex


    MSDN Community Support Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    2019年11月27日 8:28
    版主
  • 抱歉,我不知道你自己有没有验证过。

    抱歉,我也不知道我的验证方法有什么问题。

    2019年11月28日 6:49
  • 你要不要把你的代码打包上来?  这样子我们好复现错误
    2019年11月28日 8:32
  • hi,ARM830

    源码还需要整理一下,后面有空了再打包上来

    2019年11月29日 5:34