قسمت آخر از سری مجموعه Concurrency و Asynchrony
303, SeeOther
https://youtu.be/rPRWFcF450o icon

Cancellation Token in C# - Part 7
در آخرین قسمت از این سری ویدیو‌ها در مورد کنسلیشن توکن صحبت کردیم و چرایی وجودش و اینکه این توکن رو چه کسی درست میکنه کی درست میکنه چطور مدیریت میکنه.

05:10 Scenario without cancellation token
13:40 What is the cancellation token source
14:53 Demo
18:00 Cancellation Exception
19:10 Review Code of Task Class
21:09 Demo on Asp dotnet core

مدت ویدیو : 27 دقیقه 

قسمت آخر از سری مجموعه Concurrency و Asynchrony
قسمت چهارم از سری مجموعه Concurrency و Asynchrony
303, SeeOther
https://youtu.be/sGMt6ba-0d4 icon

قسمت 4- تو این ویدیو کامل مباحثی مثل Lock وMonitor وMutex وSemaphore رو بررسی کردیم و 2 نمونه از همزمانی و ددلاک رو هم توی کد دیدیم.

1:00 Why do we call the worker thread
2:47 Deadlock
09:29 Monitor and lock the object
12:36 lock(){} is Monitor
13:15 Mutex/ Semaphore/ SemaphoreSlim

لطفا در چنل یوتیوب ما عضو شوید، عضو شدن شما میتونه انرژی خوبی برای ما باشه برای تولید محتوهای بعدی، ممنونم .


مدت ویدیو : 22 دقیقه 

قسمت چهارم از سری مجموعه Concurrency و Asynchrony
قسمت سوم از سری مجموعه Concurrency و Asynchrony
303, SeeOther
https://youtu.be/LNqz15rhyWU icon

تو این ویدیو در مورد استک‌های هر ترد، پروگرم کانتر، و کانتکس سوییچ بین ترد‌ها و همچنین استیت‌های لوکال و گلوبال صحبت کردیم و در انتهای به بررسی اولویت در ترد‌ها پرداختیم 

0.50 New Example of Concurrency 

05:00 Shared / local state 

07:00 stack thread 

11:39 Program Counter 

24:40 Thread Priority 

قسمت سوم از سری مجموعه Concurrency و Asynchrony
انواع بلاکینگ و کانتکست سوییچ بین ترد های درون یه پروسس
303, SeeOther
https://youtu.be/TfoSyRyEVdo icon

در ادامه قسمت اول اینسری در مورد فرق بین پروسس و ترد صحبت کردیم و انواع بلاک شدن و کانتکست سوییچ بین ترد‌های درون یه پروسس صحبت کردیم.

01:10 Main Thread 

02:50 Multi-Thread Process 

04:25 Thread for GC & Finalization 

05:22 Demo 

08:00 Context switch on threads 

10:50 Thread Blocking 

15:11 Blocking Type (I/O and Compute Bound) 

مدت زمان ویدیو : 19 دقیقه 

انواع بلاکینگ و کانتکست سوییچ بین ترد های درون یه پروسس
قسمت اول از سری مجموعه Concurrency و Asynchrony
303, SeeOther
https://youtu.be/vIPW_JwV_jQ icon
تو این ویدیو پراسس‌ها و ترد‌ها و همچنین الگوریتم‌های اولویت بندی در سیستم عامل رو بررسی کردیم. این ویدیو اولین ویدیو از سری ویدیو‌های مربوط به مثال مالتی تردینگ و همزمانی هست، تو این سری از جلسات قراره کلا درباره ترد و پروسس و هر چیزی که مربوی به فضای همزمانی در سی شارپ هست میپردازیم.

 0:00 Description
 1:20 Process and Thread 
 04:05 FIFO scheduling algorithms
 06:20 SJF scheduling algorithms 
 09:00 Round Robin scheduling algorithms 
 13:10 Process lifecycle in CPU 
 مدت زمان ویدیو : 18 دقیقه
قسمت اول از سری مجموعه Concurrency و Asynchrony
نحوه کنترل همزمانی در EF Core
301, MovedPermanently
https://docs.microsoft.com/en-us/aspnet/core/data/ef-mvc/concurrency?view=aspnetcore-6.0 icon

نحوه مدیریت رکوردهایی که توسط چندین کاربر در آن واحد تغییر می‌یابند. به فرض یک کاربر در حال به روزرسانی یک رکورد است اما قبل از ثبت تغییرات، کاربری دیگر همان رکورد را پاک می‌کند.

نحوه کنترل همزمانی در EF Core
مدیریت مباحث همزمانی مرتبط با یک Rich Domain Model با استفاده از EFCore و الگوی Aggregate
301, MovedPermanently
https://www.kamilgrzybek.com/design/handling-concurrency-aggregate-pattern-and-ef-core/ icon

In summary, the most important issues here are:

  • The Aggregate’s main task is to protect invariants (business rules, the boundary of immediate consistency)
  • In a multi-threaded environment, when multiple threads are running simultaneously on the same Aggregate, a business rule may be broken
  • A way to solve concurrency conflicts is to use Pessimistic or Optimistic concurrency techniques
  • Pessimistic Concurrency involves the use of a database transaction and a locking mechanism. In this way, requests are processed one after the other, so basically concurrency is lost and it can lead to deadlocks.
  • Optimistic Concurrency technique is based on versioning database records and checking whether the previously loaded version has not been changed by another thread.
  • Entity Framework Core supports Optimistic Concurrency. Pessimistic Concurrency is not supported
  • The Aggregate must always be treated and versioned as a single unit
  • Domain events are an indicator, that state was changed so Aggregate version should be changed as well 
public class AggregateRootBase : Entity, IAggregateRoot
{
    private int _versionId;

    public void IncreaseVersion()
    {
        _versionId++;
    }
}
internal sealed class OrderEntityTypeConfiguration : IEntityTypeConfiguration<Order>
{
    public void Configure(EntityTypeBuilder<Order> builder)
    {
        builder.Property("_versionId").HasColumnName("VersionId").IsConcurrencyToken();
 
        //...
    }
}
var order = await _ordersContext.Orders.FindAsync(orderId);
order.AddOrderLine(request.ProductCode); 
var domainEvents = DomainEventsHelper.GetAllDomainEvents(order);
if (domainEvents.Any())
{
    order.IncreaseVersion();
}
await _ordersContext.SaveChangesAsync();


مدیریت مباحث همزمانی مرتبط با یک Rich Domain Model با استفاده از EFCore و الگوی Aggregate
پیاده سازی یک Filter سفارشی برای نگاشت استثنای همزمانی به خطاهای MadelState
200, OK
https://github.com/adamtuliper/EF5-for-Real-Web-Applications/blob/master/Gecko.Framework.Mvc/ActionFilters/HandleConcurrencyExceptionAttribute.cs icon
 public class HandleConcurrencyExceptionAttribute : FilterAttribute, IExceptionFilter
    {
        private PropertyMatchingMode _propertyMatchingMode;
        /// <summary>
        /// This defines when the concurrencyexception happens, 
        /// </summary>
        public enum PropertyMatchingMode
        {
            /// <summary>
            /// Uses only the field names in the model to check against the entity. This option is best when you are using 
            /// View Models with limited fields as opposed to an entity that has many fields. The ViewModel (or model) field names will
            /// be used to check current posted values vs. db values on the entity itself.
            /// </summary>
            UseViewModelNamesToCheckEntity = 0,
            /// <summary>
            /// Use any non-matching value fields on the entity (except timestamp fields) to add errors to the ModelState.
            /// </summary>
            UseEntityFieldsOnly = 1,
            /// <summary>
            /// Tells the filter to not attempt to add field differences to the model state.
            /// This means the end user will not see the specifics of which fields caused issues
            /// </summary>
            DontDisplayFieldClashes = 2
        }


        public HandleConcurrencyExceptionAttribute()
        {
            _propertyMatchingMode = PropertyMatchingMode.UseViewModelNamesToCheckEntity;
        }

        public HandleConcurrencyExceptionAttribute(PropertyMatchingMode propertyMatchingMode)
        {
            _propertyMatchingMode = propertyMatchingMode;
        }


        /// <summary>
        /// The main method, called by the mvc runtime when an exception has occured.
        /// This must be added as a global filter, or as an attribute on a class or action method.
        /// </summary>
        /// <param name="filterContext"></param>
        public void OnException(ExceptionContext filterContext)
        {
            if (!filterContext.ExceptionHandled && filterContext.Exception is DbUpdateConcurrencyException)
            {
                //Get original and current entity values
                DbUpdateConcurrencyException ex = (DbUpdateConcurrencyException)filterContext.Exception;
                var entry = ex.Entries.Single();
                //problems with ef4.1/4.2 here because of context/model in different projects.
                //var databaseValues = entry.CurrentValues.Clone().ToObject();
                //var clientValues = entry.Entity;
                //So - if using EF 4.1/4.2 you may use this workaround
                var clientValues = entry.CurrentValues.Clone().ToObject();
                entry.Reload();
                var databaseValues = entry.CurrentValues.ToObject();

                List<string> propertyNames;

                filterContext.Controller.ViewData.ModelState.AddModelError(string.Empty, "The record you attempted to edit "
                        + "was modified by another user after you got the original value. The "
                        + "edit operation was canceled and the current values in the database "
                        + "have been displayed. If you still want to edit this record, click "
                        + "the Save button again to cause your changes to be the current saved values.");
                PropertyInfo[] entityFromDbProperties = databaseValues.GetType().GetProperties(BindingFlags.FlattenHierarchy | BindingFlags.Public | BindingFlags.Instance);

                if (_propertyMatchingMode == PropertyMatchingMode.UseViewModelNamesToCheckEntity)
                {
                    //We dont have access to the model here on an exception. Get the field names from modelstate:
                    propertyNames = filterContext.Controller.ViewData.ModelState.Keys.ToList();
                }
                else if (_propertyMatchingMode == PropertyMatchingMode.UseEntityFieldsOnly)
                {
                    propertyNames = databaseValues.GetType().GetProperties(BindingFlags.Public).Select(o => o.Name).ToList();
                }
                else
                {
                    filterContext.ExceptionHandled = true;
                    UpdateTimestampField(filterContext, entityFromDbProperties, databaseValues);
                    filterContext.Result = new ViewResult() { ViewData = filterContext.Controller.ViewData };
                    return;
                }



                UpdateTimestampField(filterContext, entityFromDbProperties, databaseValues);

                //Get all public properties of the entity that have names matching those in our modelstate.
                foreach (var propertyInfo in entityFromDbProperties)
                {

                    //If this value is not in the ModelState values, don't compare it as we don't want
                    //to attempt to emit model errors for fields that don't exist.

                    //Compare db value to the current value from the entity we posted.

                    if (propertyNames.Contains(propertyInfo.Name))
                    {
                        if (propertyInfo.GetValue(databaseValues, null) != propertyInfo.GetValue(clientValues, null))
                        {
                            var currentValue = propertyInfo.GetValue(databaseValues, null);
                            if (currentValue == null || string.IsNullOrEmpty(currentValue.ToString()))
                            {
                                currentValue = "Empty";
                            }

                            filterContext.Controller.ViewData.ModelState.AddModelError(propertyInfo.Name, "Current value: "
                                 + currentValue);
                        }
                    }

                    //TODO: hmm.... how can we only check values applicable to the model/modelstate rather than the entity we saved?
                    //The problem here is we may only have a few fields used in the viewmodel, but many in the entity
                    //so we could have a problem here with that.
                    //object o = propertyInfo.GetValue(myObject, null);
                }

                filterContext.ExceptionHandled = true;

                filterContext.Result = new ViewResult() { ViewData = filterContext.Controller.ViewData };
            }
        }
پیاده سازی یک Filter سفارشی برای نگاشت استثنای همزمانی به خطاهای MadelState