我有一类,其中根据从外部应用程序接收到的事件来调用方法。
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不同,则不应等待。
答案 0 :(得分:1)
我将去耦传入事件和处理:
这可确保:
您也可以考虑使用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>