2


1

私はリストを操作するための画像検索機能を作ろうとしています。

リストには、例えばタイプ(TItem)の項目が含まれています。 TItemには、title、image、imageURLなどのプロパティがいくつかあります。

すべてのアイテムをスキャンし、各アイテムのimageURLを使用して各アイテムのイメージを取得しようとするリストを含むスレッドがあります。

各アイテムの画像を取得するスレッドは、次のように機能します。

終了していない間は、i:= 0からList.count-1までを開始項目として開始します。= List.Items [i]; //注:imageURLから画像を取得するのに数秒かかることがあります。 このメソッドは、// item.imageURLから画像を取得し、それをitem.imageに割り当てます。RetrieveImage(item.imageURL、item.Image);終わり;スリープ(100)終わり;

残念なことに、それは1つのケースではうまくいきません:リストがクリアされ、アイテムの画像がスレッドによって検索されているとき。

(読み書きのすべての項目はミューテックスで保護されています)。

私は何をすべきか ?

ありがとう:)

2 Answer


4


これを解決する多くの方法があります、ここに2つの例があります:

  • オブジェクトのリストを使わないでください、 `TInterfaceList`またはインターフェースの一般的なリストを使ってください。 アイテムクラスのパブリックメソッドからインターフェースを作成します。 スレッドはインターフェイス参照を維持し、参照カウントをゼロより上に保ちます。したがって、インターフェイスを実装するオブジェクトインスタンスは削除されません。 そのため、アイテムにアクセスしても安全です。

  • スレッドから直接アイテムにアクセスするのではなく、スレッドには不透明なアイテムハンドルだけを渡します。 最初、スレッドはそのハンドルを使用してイメージを取得するために必要なデータを要求します。また、リストをロックするのでアクセスは安全です。 画像が取得されると、スレッドは再びハンドルを使用して、画像をロックされたコードセクションの項目に設定します。 アイテムが有効でなくなった場合、ハンドルはアイテムに解決されず、取得されたイメージは単に削除されます。 ハンドルが再利用されていないことを確認する必要があるだけなので、たとえばリストのインデックスやアイテムのアドレスはどちらも悪い考えになります。 OTOHごとに増分される整数がうまく機能します。

2番目の方法のための単純化されたコード:

var Img:TImage; ImgHandle:TImageFromURLHandle;
...

Img:= TImage.Create; List.GetNextImageURL(ImgHandle、ImgURL)がRetrieveImage(ImgURL、Img);を開始している間は終了しないでください。 // SetImage()はスレッドセーフであり、画像アイテムがリストに存在しない場合は//何もしません(無効なハンドル)。List.SetImage(ImgHandle、Img);終わり;スリープ(100)終わり;最後にImg.Free。終わり;

あなたはハンドルとして画像URLそれ自身を使うことさえできます。

リストが空の場合、より良い方法はスレッドをブロックすることです。あなたの `Sleep()`呼び出しは基本的にはポーリングです。 オーバーヘッドはそれほど多くありませんが、それでもスタイルは良くありません。


3


基本的な問題は、ミューテックスを使用してコードがループ自体を保護しないことです。 ご存知のとおり、これはシステムを大幅に遅くする巨大なミューテックスを作成するでしょう。

これが良い解決策です:

  • forループをwhileループに置き換える

  • 次のURLを見つけるコードを作成し、そのコードをミューテックス保護します

  • 画像検索がリストに関連しない変数を使用するようにして、それがミューテックス保護を必要としないようにします。

  • URLを使用して正しいインデックスを見つけて、取得した画像を保存します。 この検索と保存はミューテックスで保護する必要があります。

このようなもの:

終了していない間はcurrenturl:= '';を始めてください。真の間にミューテックスを開始するcurrenturl:= FindNextUrl(currentUrl); currenturl = ''の場合、ミューテックスは終了します。 //これ以上URLは見つかりませんRetrieveImage(currenturl、image);ミューテックス開始インデックス:= FindUrlIndex(currenturl)List [インデックス] .image:= image;ミューテックスエンドエンド。スリープ(100)終わり;

必要なミューテックスコード、try-statementsなどを追加してください。 あなた自身。