1

特定の関数を並行して実行するプログラムが必要です。ただし、その関数は、ユーザーがプログラムを操作する方法に応じて、さまざまな結果に分岐します。ダウンロードとアップロードの 2 つのオプションがある、threadGUI.py という名前のモジュール内に単純な GUI があります。これらのオプションは、関数に関連する変数を含む辞書を作成します。これらの辞書は、thread_test.py モジュールに格納されているメイン ディクショナリに格納されます。これらは順番に実行するとうまくいきますが、並行して実行しようとすると何か問題が発生します。threadGUI.py のスレッド関連のコード:

def OnStartClick(self):
  for i in thread_test.dictList.values():        #the main dictionary is stored as a global in thread_test.py
     thread = Thread(target = thread_test.begin_tests, args = (i, ))
     thread.start()
  print "thread finished...exiting"

上記の関数は、thread_test.py モジュール内の begin_test 関数を呼び出します。関数は次のようになります。

def begin_tests(arg): 
    print arg
    print dictList
    dictItem = arg
    print dictItem
    if dictItem['Type'] == "HTTP_Downloading":
        print "DOWNLOAD"
    elif dictItem['Type'] == "FTP_Uploading":
        print "UPLOAD"
    else:
        print "Invalid input"
        sys.exit(1)

これは私のコードの単純化された例です。私の問題は、私のコードが両方ではなく、2 つのうち 1 つの関数のみを実行していることです。したがって、ダウンロード、アップロード、ダウンロードを呼び出す辞書を作成すると、目的のパターンではなく、3 つのダウンロードが実行されます。

4

1 に答える 1

2

問題は投稿されたコードにはありません:

from threading import Thread

dictList = {
    'foo': { 'Type': 'HTTP_Downloading' },
    'bar': { 'Type': 'FTP_Uploading' },
    'baz': { 'Type': 'HTTP_Downloading' }
}

def begin_tests(arg):
    print arg
    print dictList
    dictItem = arg
    print dictItem
    if dictItem['Type'] == "HTTP_Downloading":
        print "DOWNLOAD"
    elif dictItem['Type'] == "FTP_Uploading":
        print "UPLOAD"
    else:
        print "Invalid input"
        sys.exit(1)

def OnStartClick(self):
  for i in dictList.values():        #the main dictionary is stored as a global in thread_test.py
     thread = Thread(target = begin_tests, args = (i, ))
     thread.start()
  print "thread finished...exiting"

OnStartClick(None)

結果:

{'Type': 'HTTP_Downloading'}
{'baz': {'Type': 'HTTP_Downloading'}, 'foo': {'Type': 'HTTP_Downloading'}, 'bar': {'Type': 'FTP_Uploading'}}
{'Type': 'HTTP_Downloading'}
 {DOWNLOAD
{'Type': 'FTP_Uploading'}
'Type': 'HTTP_Downloading'}
{'baz': {'Type': 'HTTP_Downloading'}, 'foo': {'Type': 'HTTP_Downloading'}, 'bar': {'Type': 'FTP_Uploading'}}
{'baz': {'Type': 'HTTP_Downloading'}, 'foo': {'Type': 'HTTP_Downloading'}, 'bar': {'Type': 'FTP_Uploading'}}
 thread finished...exiting
{'Type': 'HTTP_Downloading'}
DOWNLOAD
{'Type': 'FTP_Uploading'}
UPLOAD

推測では、あなたは内部辞書を再利用しています。

アップデート:

このケースは、worker-pool-and-queue 戦略を使用することでより適切に解決できると思います。何かのようなもの:

from Queue import Queue
from threading import Thread

queue = Queue() # Replaces the dictList

threads = []
for n in range(10):
    thread = Thread(target = worker, args = (begin_tests, queue, ))
    thread.start()
    threads.append(thread)

Stop = object()
def worker(work, queue):
    while True:
        task = queue.get()
        if task is Stop:
            break
        work(task)            

次のように使用します。

queue.put({ 'Type': 'HTTP_Downloading' })
queue.put({ 'Type': 'FTP_Uploading' })
queue.put({ 'Type': 'HTTP_Downloading' })
queue.put(Stop)

これ自体は辞書を変更する問題には対処しません。他の場所で修正する必要があります。この戦略には 2 つの利点があります。タスクの順序が保持され、タスクが失われるリスクがありません。

于 2012-06-05T13:35:06.573 に答える