You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

多进程文件加密场景下tkinter ProgressBar进度异常问题求助

Tkinter多进程文件加密程序进度条异常修复

核心问题原因

  • Tkinter控件不是线程安全的,原代码在线程池的工作线程中直接修改进度条属性、调用root.update_idletasks(),跨线程操作UI会导致更新时序混乱,出现进度跳变、卡顿问题
  • enc函数内的计数变量x为局部变量,每次处理文件都会被重置为0,百分比计算逻辑完全错误
  • 进程池使用阻塞的apply()方法调用加密函数,无法充分发挥多进程并发能力
  • 没有全局线程安全的进度计数器,无法正确累计已完成的加密任务数

修复实现

首先新增全局计数器和锁保证计数安全:

import threading
completed_tasks = 0
task_lock = threading.Lock()

修改加密逻辑,移除工作线程中的UI操作,通过事件机制通知主线程更新UI:

def enc(key, process_pool, file):
    with open(file,'rb') as original_file:
        original = original_file.read()
    encrypted = process_pool.apply(encryptfn, args=(key, original,))
    with open (file,'wb') as encrypted_file:
        encrypted_file.write(encrypted)
    # 线程安全累加计数
    global completed_tasks
    with task_lock:
        completed_tasks +=1
    # 仅向主线程发送更新通知,不直接操作UI
    root.event_generate("<<update_progress>>", when="tail")

在主线程绑定进度更新事件,所有UI操作统一在主线程执行:

def update_progress(*args):
    global completed_tasks
    total = len(files)
    progress = (completed_tasks / total) * 100
    pbar['value'] = progress
    percent.set(f"{int(progress)}%")
    root.update_idletasks()

# 主程序初始化时绑定事件
progbar()
percent.set('0%')
root.bind("<<update_progress>>", update_progress)

可进一步简化池逻辑,移除冗余的线程池嵌套,直接用进程池异步实现:

def encfile():
    global completed_tasks, files
    completed_tasks = 0
    password = bytes('asdasd', 'utf-8')
    salt = bytes('zxcasd','utf-8')
    files = filistbox.get(0,'end')

    if len(files) == 0:
        fierrorbox()
        return
    elif len(password) == 0:
        passerrorbox()
        return
    
    file_enc_button['state']='disabled'
    browsefi['state']='disabled'

    kdf = PBKDF2HMAC(
        algorithm=hashes.SHA256(),
        length=32,
        salt=salt,
        iterations=100,
        backend=default_backend())
    key = base64.urlsafe_b64encode(kdf.derive(password))

    pool_size = min(cpu_count(), len(files))
    with Pool(pool_size) as process_pool:
        results = [process_pool.apply_async(encryptfn, args=(key, open(f,'rb').read())) for f in files]
        for idx, res in enumerate(results):
            encrypted = res.get()
            with open(files[idx], 'wb') as f:
                f.write(encrypted)
            completed_tasks +=1
            root.event_generate("<<update_progress>>", when="tail")

    root.event_generate("<<encryption_done>>")
    
    file_enc_button['state']='active'
    browsefi['state']='active'

内容的提问来源于stack exchange,提问作者Sanket

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.26 15:39:03