我在Python 3.5中实现了一项服务,应该定期通过网络加载文件。我想避免在加载时阻塞主线程。为了避免将线程和共享内存的复杂性引入我的应用程序,我想使用带有asyncio包的事件循环来检测它。
要运行事件循环,我找到了private void CreatePopup(Long id) {
final LayoutInflater Manual = LayoutInflater.from(this);
final View textEntryView = Manual.inflate(update, null);
final EditText infoData = (EditText) textEntryView.findViewById(R.id.InfoData);
final AlertDialog.Builder alert = new AlertDialog.Builder(this);
final TextView TextSet = (TextView) textEntryView.findViewById(R.id.product);
final Button Accept = (Button) textEntryView.findViewById(R.id.button);
final Button Delete = (Button) textEntryView.findViewById(R.id.delete);
final SQLite db = new SQLite(this);
final Long _id = id;
final SQLiteDatabase X = db.getReadableDatabase();
final Cursor c;
c = X.rawQuery("SELECT Product FROM Inventory WHERE _id =" + _id, null);
c.moveToFirst();
final String Data = c.getString(c.getColumnIndexOrThrow("Product"));
TextSet.setText(Data);
c.close();
Accept.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if (infoData.length() != 0) {
final Editable Data = infoData.getText();
db.UpdateRecord(Data, _id);
db.close();
Snackbar.make(textEntryView, "Updated", Snackbar.LENGTH_LONG).setDuration(700).show();
}
else {
Toast toast = Toast.makeText(getApplicationContext(),
"Input Quantity!", Toast.LENGTH_SHORT);
toast.show();
}
}});
Delete.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
db.DeleteRecord(_id);
db.close();
Snackbar.make(textEntryView, "Removed", Snackbar.LENGTH_LONG).setDuration(700).show();
}
});
alert.setTitle("Update Quantity").setView(textEntryView);
alert.setPositiveButton("Done", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
CreateListView();
}
});
alert.show();
}
和AbstractEventLoop.run_forever()
方法,但两者似乎都在调用时阻塞主线程。我发现避免这种情况的唯一方法是在不同的线程中启动循环。但是如果我还在使用线程,那么使用事件循环是没有意义的。
所以我的问题是:是否可以在后台启动asyncio事件循环而不产生线程或进程?
答案 0 :(得分:2)
如果您的整个程序在没有Future
事件循环的情况下运行,则在新事件循环中仅运行一个任务并没有多大意义。相反,请尝试使用复杂程度较低的concurrent.futures
库。任何被调用的任务都会立即返回.done()
个实例,该实例具有.result()
和import time
from concurrent.futures.thread import ThreadPoolExecutor
def fetcher():
print("fetching...")
time.sleep(2)
print("got it!")
return 42
with ThreadPoolExecutor(max_workers=10) as executor:
fut = None
for i in range(100):
if i % 10 == 2:
fut = executor.submit(fetcher)
print(i, fut)
if fut and fut.done():
result = fut.result() # can raise an error
print("Done! Got:", result)
fut = None
time.sleep(0.5)
方法:
You+do+not+have+permission+to+get+these+payment+details
答案 1 :(得分:1)
您可以使用run_in_executor
方法。使用此方法运行的每个函数都在自己的线程中运行(并行)。
AbstractEventLoop.run_in_executor()方法可以与线程池执行程序一起使用,以在不同的线程中执行回调,从而不阻塞事件循环的线程。
executor参数应该是Executor实例。如果执行程序为None,则使用默认执行程序。
例如:
import asyncio
def load_file_over_network(file_name):
# do the file loading
pass
loop = asyncio.get_event_loop()
file_name = 'FILE_NAME'
# load the file without blocking
loop.run_in_executor(None, load_file_over_network, file_name)
# do some other stuff in the main thread
# while the synchronous code above is running in other threads, the event loop
# can go do other things
# load the file again without blocking
loop.run_in_executor(None, load_file_over_network, file_name)
希望这有用:)
答案 2 :(得分:1)
嗯,Yuval Pruss's answer部分正确。实际上,loop.run_in_executor()
的{{3}}参数可以是ThreadPoolExecutor
(默认值)或ProcessPoolExecutor
(现在在asyncio中已弃用)。
因此答案是否定的,您不能在所有其他代码都同步的情况下在后台运行asyncio
Task
。或者您重写您的应用程序,以便它对每个任务使用asyncio
,或者您必须使用线程或进程。