如何在C#中执行某些操作之前等待事件发生?

时间:2019-09-16 12:16:18

标签: c# multithreading event-handling

我有一类,其中根据从外部应用程序接收到的事件来调用方法。

public void ProcessItems(Store id,Items items)
{
    //Some logic
     UpdateValidItems(id,validItems)

}

public void UpdateValidItems(Store id,Items items)
{
        //Save in DB
}

在处理UpdateValidItems时,外部应用程序可能会调用“ ProcessItems”。我希望,如果正在处理UpdateValidItems并在UpdateValidItems处理期间调用了事件,则它应等待UpdateValidItems完成。有什么办法吗?

此外,一次可以处理多个商店。因此,它只应等待基于存储的存储。如果storeId不同,则不应等待。

2 个答案:

答案 0 :(得分:1)

我将去耦传入事件和处理:

  1. 让线程等待Blocking Queue
  2. 事件将写入阻塞队列
  3. 从0开始的线程。)得到通知,将1个“行”(ID和项)出队
  4. 所述线程处理项目
  5. 线程再次等待,或者如果事件同时添加了更多行:处理直到队列为空,然后再次等待。

这可确保:

  • 一次只更改一个商店
  • 事件快速返回
  • 同一商店的后续事件不会干扰当前的处理。

您也可以考虑使用DataFlow来实现类似的方法。


编辑/基本示例:

public class Handler
{
    private readonly BlockingCollection<QueueEntry> _queue = new BlockingCollection<QueueEntry>();
    private readonly CancellationTokenSource _cts = new CancellationTokenSource();

    // I used a Form with a button to simulate events, so you'll have to adapt that..
    public Handler(Form1 parent)
    {
        // register for incoming Items
        parent.NewItems += Parent_NewItems;
        // Start processing on a long running Pool-Thread
        Task.Factory.StartNew(QueueWorker, TaskCreationOptions.LongRunning);
    }

    // Stop Processing
    public void Shutdown( bool doitnow )
    {
        // Mark the queue "complete" - adding is now forbidden.
        _queue.CompleteAdding();
        // If you want to stop NOW, cancel all operations
        if (doitnow ) { _cts.Cancel(); }
        // Else the Task will run until the queue has been processed.
    }

    // This is all that happens on the EDT / Main / UI Thread
    private void Parent_NewItems(object sender, NewItemsEventArgs e)
    {
        try
        {
            _queue.Add(new QueueEntry { Sender = sender, Event = e });
        }
        catch (InvalidOperationException)
        {
            // dontcare ? I didn't - You may, though.
            // Will be thrown if the queue has been marked complete.
        }
    }

    private async Task QueueWorker()
    {
        // While the queue has not been marked complete and is empty
        while (!_queue.IsCompleted)
        {
            QueueEntry entry = null;
            try
            {
                // Wait until an entry is available or until canceled.
                entry = _queue.Take(_cts.Token); 
            }
            catch ( OperationCanceledException )
            {
                // dontcare
            }
            if (entry != null)
            {
                await Process(entry, _cts.Token);
            }
        }
    }

    private async Task Process(QueueEntry entry, CancellationToken cancel)
    {
        // Dummy Processing...
        await Task.Delay(TimeSpan.FromSeconds(entry.Event.Items), cancel);
    }
}

public class QueueEntry
{
    public object Sender { get; set; }
    public NewItemsEventArgs Event { get; set; }
} 

当然,可以对此进行调整,以实现一些并发/并行处理。

答案 1 :(得分:0)

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout 
  xmlns:android="http://schemas.android.com/apk/res/android"
  xmlns:app="http://schemas.android.com/apk/res-auto"
  android:layout_width="match_parent"
  android:layout_height="match_parent">

<ImageView
    android:id="@+id/img"
    android:layout_width="0dp"
    android:layout_height="0dp"
    android:scaleType="centerCrop"
    android:src="@drawable/rose"
    app:layout_constraintBottom_toTopOf="@+id/text"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintTop_toTopOf="parent" />

<TextView
    android:id="@+id/text"
    android:layout_width="0dp"
    android:layout_height="0dp"
    app:layout_constraintHeight_percent=".15"
    android:gravity="center"
    android:ellipsize="end"
    android:maxLines="3"
    android:text="In May 2019, Italian broadcaster RAI announced that it had begun planning the 2020 edition of the Sanremo Music Festival. It was not confirmed whether the festival would be used to select Italy's participant for 2020."
    android:textColor="#000000"
    android:textSize="16dp"
    app:layout_constraintBottom_toBottomOf="parent"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintStart_toStartOf="parent" />
</android.support.constraint.ConstraintLayout>