Property blocks get until how elegantly implemented by set?

some attributes that are asynchronously assigned to the background thread during program initialization may be ready for UI before the completion of set, that is, the user can operate. If you need to get some attribute that has not yet been set in the operation, I hope the code will block until set continues to execute. Of course, if set is ready before get, there will be no blocking. So this kind of blocking can only be used once at most. I don"t think it"s authentic to get a lock or signal object for this purpose. This scenario should be very typical. I wonder if there is a more elegant way (such as adding a [xxx] feature to this attribute) to write this attribute?


use ide/concepts/threading/thread-synchronization-sharpsynchronization-events-and-wait-handles" rel=" nofollow noreferrer "> Synchronize event :

using System;
using System.Dynamic;
using System.Reflection;
using System.Threading.Tasks;

namespace Test6
{
    class Program
    {
        static void Main(string[] args)
        {
            dynamic t = new DynamicProxy(new Test());
            Console.WriteLine("[" + DateTime.Now.ToString("HH:mm:ss.fff") + "] " + t.NormalProperty);
            Console.WriteLine("[" + DateTime.Now.ToString("HH:mm:ss.fff") + "] " + t.LazyPropertyWithDefaultValue);
            Console.WriteLine($"[{DateTime.Now.ToString("HH:mm:ss.fff")}] pretending doing something that will takes 3s");
            System.Threading.Thread.Sleep(3000);
            Console.WriteLine($"[{DateTime.Now.ToString("HH:mm:ss.fff")}] something is done in 3s");
            var lazyValue = t.LazyProperty;
            Console.WriteLine("[" + DateTime.Now.ToString("HH:mm:ss.fff") + "] " + lazyValue);
            Console.WriteLine("[" + DateTime.Now.ToString("HH:mm:ss.fff") + "] " + t.LazyPropertyWithDefaultValue);
            Console.ReadLine();
        }
    }

    [LazyPropertyIncluded]
    public class Test
    {
        public string NormalProperty { get; set; }

        [LazyProperty(InitializerName = "InitLazyProperty")]
        public string LazyProperty { get; }

        [LazyProperty(HasDefaultValue =true, Defaultalue = "LazyPropertyWithDefaultValue Default Value")]
        public string LazyPropertyWithDefaultValue { get; }

        protected Task<string> InitLazyProperty = new Task<string>(() =>
        {
            Console.WriteLine($"[{DateTime.Now.ToString("HH:mm:ss.fff")}] start initializing LazyProperty");
            System.Threading.Thread.Sleep(5000);
            return "LazyProperty initialized";
        });

        protected Task<string> InitLazyPropertyWithDefaultValue = new Task<string>(() =>
        {
            Console.WriteLine($"[{DateTime.Now.ToString("HH:mm:ss.fff")}] start initializing LazyPropertyWithDefaultValue");
            System.Threading.Thread.Sleep(5000);
            return "LazyPropertyWithDefaultValue initialized";
        });

        public Test()
        {
            this.NormalProperty = "NormalProperty";
        }
    }

    [AttributeUsage(AttributeTargets.Property)]
    public class LazyPropertyAttribute : Attribute
    {
        public string InitializerName { get; set; }
        public bool HasDefaultValue { get; set; }
        public object Defaultalue { get; set; }
    }

    [AttributeUsage(AttributeTargets.Class)]
    public class LazyPropertyIncludedAttribute : Attribute { }

    public class DynamicProxy : DynamicObject
    {
        readonly object[] _sources;

        public DynamicProxy(params object[] sources)
        {
            this._sources = sources;

            // run init method for lazy properties
            foreach (var src in this._sources)
            {
                var attr = src.GetType().GetCustomAttribute<LazyPropertyIncludedAttribute>();
                if (attr != null)
                {
                    foreach (var prop in src.GetType().GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic))
                    {
                        var propAttr = prop.GetCustomAttribute<LazyPropertyAttribute>();
                        if (propAttr != null)
                        {
                            var initTask = propAttr.InitializerName ?? "Init" + prop.Name;
                            var task = src.GetType().GetField(initTask, BindingFlags.Instance | BindingFlags.NonPublic);
                            if (task != null)
                            {
                                ((Task)task.GetValue(src)).Start();
                            }
                            else
                            {
                                throw new MethodAccessException("Cannot find initialization method [" + initTask + "] for lazy prop: " + prop.Name);
                            }
                        }
                    }
                }
            }
        }

        public override bool TryGetMember(GetMemberBinder binder, out object result)
        {
            object propValue = null;

            foreach (var src in this._sources)
            {
                var prop = src.GetType().GetProperty(binder.Name);
                if (prop != null)
                {
                    var propAttr = prop.GetCustomAttribute<LazyPropertyAttribute>();
                    if (propAttr == null)
                    {
                        propValue = prop.GetValue(src);
                    }
                    else
                    {
                        var initTask = propAttr.InitializerName ?? "Init" + prop.Name;
                        var task = src.GetType().GetField(initTask, BindingFlags.Instance | BindingFlags.NonPublic).GetValue(src) as Task;
                        if (!task.IsCompleted && propAttr.HasDefaultValue)
                        {
                            propValue = propAttr.Defaultalue;
                        }
                        else
                        {
                            Task.WaitAll(task);
                            propValue = Convert.ChangeType(task.GetType().GetProperty("Result").GetValue(task), prop.PropertyType);
                        }
                    }
                    break;
                }
            }

            if (propValue == null)
            {
                propValue = binder.Name + " from dynamic proxy";
            }

            result = propValue;

            return true;
        }
    }
}
MySQL Query : SELECT * FROM `codeshelper`.`v9_news` WHERE status=99 AND catid='6' ORDER BY rand() LIMIT 5
MySQL Error : Disk full (/tmp/#sql-temptable-64f5-1e939be-146d.MAI); waiting for someone to free some space... (errno: 28 "No space left on device")
MySQL Errno : 1021
Message : Disk full (/tmp/#sql-temptable-64f5-1e939be-146d.MAI); waiting for someone to free some space... (errno: 28 "No space left on device")
Need Help?