1

我需要我的程序并行执行某个功能。但是根据用户与程序的交互方式,该功能会产生不同的结果。我在一个名为 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)

这是我的代码的简化示例。我的问题是我的代码只执行两个函数中的一个,而不是两个函数。因此,如果我创建了一个名为下载、上传、下载的字典,那么它将执行三个下载,而不是所需的模式。

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

猜测一下,您正在重用内部字典。

更新:

我认为这种情况最好通过使用工作池和队列策略来解决。就像是:

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)

这本身并不能解决改变字典的问题;这必须在其他地方修复。这种策略有两个好处:它确实保留了任务的顺序,并且不会冒丢失任务的风险:dict 提供有限的并发保证,而 Queue() 保证是线程安全的。

于 2012-06-05T13:35:06.573 回答