从多个线程同时从.net库调用方法时,结果不完整

时间:2019-02-14 08:07:17

标签: python multithreading

我正在使用一个GUI来显示工厂中某些工具的状态。可以通过集成到.dll文件中的Web服务来请求状态。当我的GUI应用程序启动时,我想同时请求所有工具的状态。为此,我为每个工具创建一个线程,然后调用一个应该获取工具状态的方法。我得到了一些正确的响应,但是大约有一半的线程根本不提供响应,有些返回了错误的值。

如果我一个接一个地运行请求,那么一切都很好。但这花了太长时间。

def request_states(self, resource, i):
    # self.driver.GetToolState is a specific method defined in a dll
    # it accesses a webservice to request data
    result = self.driver.GetToolState(str(resource), str(self.site))
    self.statedata_dic[i] = [result, state]

    if result.Success:
        print(str(resource) + result.ToolState.Description)
    else:
        print(str(resource) + 'no state av')



state_threads = []

# create a thread for every resource
for i in range(len(self.resources)):

    s_t = threading.Thread(target=self.request_states, args=[self.resources[i], i])
    # start thread
    s_t.start()

    state_threads.append(s_t)

for s_t in state_threads:
    s_t.join()

self.resources是一个包含30个条目的列表。 启动线程时似乎出现了错误。

我得到什么: 1待机 2待机 3待机 4已禁用 5无 6待机 7待机 8待机 9无 10待机 11待机 12无 13待机 14待机 15无状态AV 16待机 17待机 18待机 19待机

我想要什么/一个接一个地运行线程时得到什么(没有“ no state av”,所有30个线程都提供响应):

1待机 2已禁用 3待机 4待机 5无 6无 7待机 8待机 9无 10待机 11待机 12待机 13待机 14待机 15待机 16待机 17待机 18待机 19待机 20待机 21待机 22待机 23待机 24待机 25待机 26待机 27待机 28个 29待机 30待机

1 个答案:

答案 0 :(得分:0)

您的问题很可能是由Python的GIL引起的。尽管您期望线程只会并行化您的请求,但实际上介于两者之间,并且特定于Python。

根据Python's wiki,“ GIL可以使与I / O绑定的线程比CPU绑定的线程更早地进行调度。它可以防止传递信号。”

如果您仍然希望这样做,可以在线程内添加带有退避机制的重试:

import time

def request_states(self, resource, i):
    # self.driver.GetToolState is a specific method defined in a dll
    # it accesses a webservice to request data
    backoff = 3
    while backoff:
        result = self.driver.GetToolState(str(resource), str(self.site))

        if result.Success:
            backoff = 0
            self.statedata_dic[i] = [result, state]
            print(str(resource) + result.ToolState.Description)
            break
        else:
            print(str(resource) + 'no state av')
        backoff -= 1
        # increase time wait with every backoff decrement 
        # so that I increase the chances to receive a correct response
        time.sleep(0.1 * (5 - backoff))