import curses, threading, sys
def thread():
a = curses.initscr()
curses.noecho()
curses.cbreak()
a.keypad(True)
while True:
char = a.getch()
if char == curses.KEY_RESIZE:
print("key_resize", file=sys.stderr)
else:
print("other", file=sys.stderr)
threading.Thread(target=thread).start()
当我自己运行这个功能时,一切都运行得很好 - KEY_RESIZE被发送,一切都很好。当我从一个线程内部调用getch()时出现问题 - 关键事件似乎工作正常(我没有详尽或广泛地测试)但是KEY_RESIZE永远不会被发送。
我做错了什么,或者有没有办法解决这个问题,这样无论线程如何都会发送KEY_RESIZE?
我已尝试在屏幕内部和外部初始化屏幕,以及Python 3.4.3上的两个不同的终端模拟器(gnome-terminal和konsole)。
打印发送到stderr(被重定向到另一个终端),因为curses会破坏屏幕输出。我也没有处理在此代码中修复终端,因此您需要重置它以使其恢复正常。
答案 0 :(得分:0)
通常,curses不是线程安全的。如果您在一个线程中完成所有工作,则可以使curses应用程序正常工作。否则,你会得到意想不到的行为......
ncurses有一个编译时配置,它提供了基本的支持(即一个更好的起点),但是你不太可能在预先打包的形式中遇到这种情况,尽管它是在几年前推出的(参见FAQ {{3 }})。
进一步阅读:
在初始化期间,ncurses为using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using PlayFab;
using PlayFab.ClientModels;
public class PlayFabManager : MonoBehaviour {
public string PlayFabId;
void Login(string titleId)
{
LoginWithCustomIDRequest request = new LoginWithCustomIDRequest()
{
TitleId = titleId,
CreateAccount = true,
CustomId = SystemInfo.deviceUniqueIdentifier
};
PlayFabClientAPI.LoginWithCustomID(request, (result) => {
PlayFabId = result.PlayFabId;
Debug.Log("Got PlayFabID: " + PlayFabId);
if(result.NewlyCreated)
{
Debug.Log("(new account)");
}
else
{
Debug.Log("(existing account)");
SetUserData();
GetUserData();
}
},
(error) => {
Debug.Log("Error logging in player with custom ID:");
Debug.Log(error.ErrorMessage);
});
}
void GetUserData()
{
GetUserDataRequest request = new GetUserDataRequest()
{
PlayFabId = PlayFabId,
Keys = null
};
PlayFabClientAPI.GetUserData(request,(result) => {
Debug.Log("Got user data:");
if ((result.Data == null) || (result.Data.Count == 0))
{
Debug.Log("No user data available");
}
else
{
Debug.Log (result.Data["age"].Value);
foreach (var item in result.Data)
{
Debug.Log(" " + item.Key + " == " + item.Value.Value);
}
}
}, (error) => {
Debug.Log("Got error retrieving user data:");
Debug.Log(error.ErrorMessage);
});
}
void SetUserData()
{
UpdateUserDataRequest request = new UpdateUserDataRequest()
{
Data = new Dictionary(){
{"Ancestor", "Arthur"},
{"Successor", "Fred"}
}
};
PlayFabClientAPI.UpdateUserData(request, (result) =>
{
Debug.Log("Successfully updated user data");
}, (error) =>
{
Debug.Log("Got error setting user data Ancestor to Arthur");
Debug.Log(error.ErrorDetails);
});
}
void Awake(){
PlayFabSettings.TitleId = "HIDDEN"; //your title id goes here.
}
// Use this for initialization
void Start () {
Login ("HIDDEN");
}
// Update is called once per frame
void Update () {
}
}
和其他一些人添加了信号处理程序。使用SIGWINCH
,我可以看到python正在捕获strace
并忽略它:
SIGWINCH
由于 python 已经建立了信号处理程序, ncurses 不再能够看到2722 <... futex resumed> ) = ? ERESTARTSYS (To be restarted if SA_RESTART is set)
2722 --- SIGWINCH {si_signo=SIGWINCH, si_code=SI_KERNEL} ---
2722 rt_sigreturn({mask=[]}) = -1 EINTR (Interrupted system call)
2722 futex(0x7f94d4000c10, FUTEX_WAIT_PRIVATE, 0, NULL) = ? ERESTARTSYS (To be restarted if SA_RESTART is set)
2722 --- SIGWINCH {si_signo=SIGWINCH, si_code=SI_KERNEL} ---
2722 rt_sigreturn({mask=[]}) = -1 EINTR (Interrupted system call)
2722 futex(0x7f94d4000c10, FUTEX_WAIT_PRIVATE, 0, NULL) = ? ERESTARTSYS (To be restarted if SA_RESTART is set)
2722 --- SIGINT {si_signo=SIGINT, si_code=SI_KERNEL} ---
2722 rt_sigreturn({mask=[]}) = -1 EINTR (Interrupted system call)
2722 write(2, "Exception ignored in: <module 'threading' from '/usr/lib/python3.4/threading.py'>\n", 82) = 82
2722 write(2, "Traceback (most recent call last):\n", 35) = 35
2722 write(2, " File \"/usr/lib/python3.4/threading.py\", line 1285, in _shutdown\n", 66) = 66
2722 open("/usr/lib/python3.4/threading.py", O_RDONLY|O_CLOEXEC) = 4
,并且不会传递SIGWINCH
。据推测,这是在python中完成的,以减轻线程配置中信号的问题。
也许是相关信息: