Project Details: In this WPF project, video is displayed on the number of structures. In fact, it is a kind of simulator that simulates the display of video on the LEDs installed on the structure or building.
private async Task PlayBinAsync()
{
InitBinList();
if (animPlayingMode == AnimPlayingMode.ParallelSynchronous)
{
List<Task> runningTasks = new List<Task>();
Coordinator.Clear();
for (int i = 0; i < Products.Count; i++)
{
Coordinator.Add(0);
Task runningTask = ReadDisplayBinFrames(Products[i], true);
runningTasks.Add(runningTask);
#if DEBUG
Debug.WriteLine($"LedProducts Count: {Products[i].LastFrameRead} of Product {i}");
#endif
}
await Task.WhenAll(runningTasks);
}
}
public async Task ReadDisplayBinFrames(Product product, bool PlayMode)
{
BinFile.SetPlayMode(PlayMode);
while (BinFile.IsPlayMode)
{
for (int currentFrameNumber = product.LastFrameRead; currentFrameNumber <= product.BinFiles.TotalGame; currentFrameNumber++)
{
await Task.Run(() =>
{
product.BinFiles.GetSphereColorFromBin(product.BinFiles.GetFrame(currentFrameNumber), product.Wiring);
product.LastFrameRead = currentFrameNumber;
#if DEBUG
Debug.WriteLine($"LastFrameRead {product.LastFrameRead}");
#endif
product.Wiring.SetSphereColor(product.DelayPlay);
});
Coordinator[product.ProductId] += 1;
await AllowPlayAsync(Coordinator);
if (currentFrameNumber >= product.BinFiles.TotalGame)
{
product.LastFrameRead = 0;
}
if (animPlayingMode == AnimPlayingMode.SerialAsync)
{
BinFile.SetPlayMode(false);
}
}
}
}
private async Task AllowPlayAsync(List<int> input)
{
if (input.All(o => o == input[0]))
{
signal.Release();
}
else
{
await signal.WaitAsync();
}
}
List<int> Coordinator = new List<int>();
private SemaphoreSlim signal = new SemaphoreSlim(0, 1);
Project requirements:
1- I want all the structures or buildings to run the videos in unison and not even one frame behind or one frame forward. 2- The project should run continuously and should not stop playing the video until it stops.
In order for the frames to be executed together on the structures, I store the number of executed frames in a list and wait for all the frames to meet and become one using the AllowPlayAsync method. It is equalized, the work continues.
But unfortunately it does not work properly!
After searching a lot, I modified and optimized the previous code as follows: This code works well and accurately, but if I want one of the products to work separately or separately from other products, it will not work and it will immediately coordinate with other products. I decided to use the "Products list" instead of the "Coordinator list", but for unknown reasons, after running the AllowPlayAsync method for a few frames, it gets stuck in the wait mode and does not exit from this mode.
private volatile static SemaphoreSlim signal = new SemaphoreSlim(0);
public volatile static ObservableCollection<Product> Products;
private void ImportProducts()
{
// After Import Products
// The number of members in the Products Collection should be equal to the number of members in the Products list.
Products = new ObservableCollection<Product>();
}
public async Task ReadDisplayBinFrames(Product product, bool PlayMode)
{
product.BinFiles.IsPlayMode = PlayMode;
for (int currentFrameNumber = product.LastFrameRead; currentFrameNumber <= product.BinFiles.TotalGame && product.BinFiles.IsPlayMode; currentFrameNumber++)
{
await Task.Run(() =>
{
product.LastFrameRead = currentFrameNumber;
AllowPlayAsync();
product.BinFiles.GetSphereColorFromBin(product.BinFiles.GetFrame(currentFrameNumber), product.Wiring);
#if DEBUG
Debug.WriteLine($"LastFrameRead {product.LastFrameRead} - PlayMode: {product.BinFiles.IsPlayMode}");
#endif
SetSphereColor(product.Wiring,product.DelayPlay);
if (currentFrameNumber >= product.BinFiles.TotalGame)
{
product.LastFrameRead = currentFrameNumber = -1;
}
Application.Current.Dispatcher.InvokeAsync(() =>
{
if (animPlayingMode == AnimPlayingMode.SerialAsync)
{
product.BinFiles.IsPlayMode = false;
}
});
});
}
}
private void AllowPlayAsync()
{
while (true)
{
if (Coordinator.ToList().All(o => o == Coordinator[0]))
{
signal.Release();
return;
}
else
{
signal.Wait();
}
}
}