Lệnh trì hoãn AppleScript không hoạt động kể từ khi chuyển sang Yosemite


10

Lưu ý: Sự delaycố với đã được khắc phục trong OS X 10.11 El Capitan.

Kể từ khi tôi nâng cấp lên Yosemite, các bản Apples sử dụng độ trễ đã ngừng hoạt động. Làm thế nào tôi có thể sửa lỗi này?

Đây là Applescript đơn giản nhất thế giới, vì một ví dụ dễ hiểu:

set volume output volume 0
delay 5
set volume output volume 20
delay 5
set volume output volume 0
delay 5
set volume output volume 20
delay 5
set volume output volume 0
delay 5
set volume output volume 20
delay 5
set volume output volume 0

Điều đó sẽ mất 30 giây để hoàn thành. Nếu tôi chạy nó trong Script Editor (trước đây là Applescript Editor) thì mất 30 giây để hoàn thành. Nhưng nếu tôi lưu tập lệnh này dưới dạng một ứng dụng, khi tôi khởi chạy ứng dụng, sự chậm trễ sẽ bị bỏ qua và ứng dụng mất một phần giây để hoàn thành.

Làm cách nào tôi có thể buộc Applescript trì hoãn trong một khoảng thời gian xác định trước khi chuyển sang bước tiếp theo? Đây có phải là một trục trặc Yosemite? Có một cách giải quyết đáng tin cậy?


Điều này hoạt động như mong đợi trên máy Mac của tôi (10.10.1)
markhunte

Bất cứ ý tưởng những gì gây ra nó không hoạt động trên của tôi? Để làm rõ: nó hoạt động trong Script Editor, nhưng nếu tôi lưu tập lệnh dưới dạng một ứng dụng và sau đó khởi chạy ứng dụng, sự chậm trễ sẽ bị bỏ qua. Đó là điều kỳ lạ nhất.
2oh1

Tôi có cùng một vấn đề vào ngày 10.10.3
Thomas Tempelmann

Báo cáo với Apple: openradar.me/21588747
Thomas Tempelmann

1
Sự cố này đã được khắc phục trong OS X 10.11 El Capitan.
Chris Trang

Câu trả lời:


7

Lưu ý: Sự delaycố với đã được khắc phục trong OS X 10.11 El Capitan.

@ 2oh1, bạn có ý tưởng cơ bản đúng trong câu trả lời của mình, nhưng đây là câu trả lời đầy đủ và chính xác:

Cách hợp lý duy nhất để giải quyết vấn đề này là gọi "độ trễ" trong vòng lặp để đảm bảo thời lượng mong muốn trôi qua trước khi tiếp tục. Cách tốt nhất để làm điều này là ghi đè "độ trễ" bằng trình xử lý tùy chỉnh:

on delay duration
  set endTime to (current date) + duration
  repeat while (current date) is less than endTime
    tell AppleScript to delay endTime - (current date)
  end repeat
end delay

Điều này cho phép bạn giữ nguyên phần còn lại của tập lệnh và bạn có thể sử dụng "độ trễ" bình thường, ví dụ:

delay 5
display alert "I like cake!"

[LƯU Ý: Thông thường, trình xử lý tùy chỉnh sẽ sử dụng "thời gian trì hoãn tiếp tục" để gọi "độ trễ" tích hợp, nhưng tôi thấy rằng, mặc dù điều này hoạt động trong Script Editor, nó trả về lỗi khi được sử dụng trong một applet (có thể ' t tiếp tục trì hoãn. (-1708). Tôi đã khắc phục vấn đề đó bằng cách trực tiếp yêu cầu AppleScript xử lý lệnh trì hoãn thay vì sử dụng "tiếp tục" để đến đó.]

Vấn đề là delayxử lý đầu vào của người dùng trong khi tạm dừng tập lệnh, do đó bạn vẫn có thể nhấp vào các menu hoặc cửa sổ được hiển thị bởi một applet và có một lỗi (được sửa trong 10.11) trong đó đầu vào của người dùng delaykhông chờ toàn bộ thời gian trước khi tiếp tục thực thi tập lệnh . Nếu bạn không tương tác với applet, hãy delayhoạt động chính xác.


Có phải tất cả điều này là một lỗi, hoặc có một lý do trì hoãn đang làm việc theo cách này với Yosemite?
2oh1

Đó là một lỗi mà sự chậm trễ không trì hoãn.
Chris Trang

Nó thật kì lạ. Tôi đã mày mò với một applescript sử dụng độ trễ vào đêm khác, và đột nhiên, sự chậm trễ đã hoạt động chính xác trở lại. Tôi giả sử lỗi đã được sửa. Một giờ sau, mặc dù không có gì thay đổi, lỗi đã quay trở lại. Tôi thực sự bối rối. Nó không quan trọng mặc dù. Tôi đang sử dụng một biến để đặt thời gian và độ trễ cho đến năm phút sau (ví dụ) và nó hoạt động hoàn hảo. Vì vậy, ... vấn đề đã được giải quyết, nhưng điều đó không giải thích được tại sao vấn đề tồn tại. Thú vị, hấp dẫn, thú vị.
2oh1

1
Vì Apple ngớ ngẩn. Phần mềm của Apple kém tin cậy hơn nhiều kể từ khi họ bắt đầu phát hành OS X hàng năm. Tôi nhớ các phiên bản nhỏ hơn của OS X (như 10.6.8) trong đó HĐH là rock-solid. Bạn không có được trải nghiệm đó nữa.
William T Froggard

Nếu đó là một lỗi (mà tôi đồng ý), tại sao điều này vẫn chưa được sửa, tôi tự hỏi. Có ai ở đây đã làm một báo cáo radar? Sau đó, xin vui lòng gửi ID của nó? (hoặc / cũng đăng trên openradar.me)
Thomas Tempelmann

5

Trong khi chiến đấu với cùng một vấn đề, tôi đã gặp câu trả lời này cho một câu hỏi không liên quan và quyết định thử nó và nó dường như có hiệu quả với tôi.

Đơn giản chỉ cần thay thế delay 5bằng do shell script "/bin/sleep 5"và nhận được kết quả tương tự.


Cám ơn vì đã chia sẻ! Như tôi đã nói ở trên, tôi không thể kiểm tra điều này bởi vì, vì những lý do không có ý nghĩa với tôi, độ trễ 5 đang hoạt động như bình thường đối với tôi ngay bây giờ (tôi vừa thử lại một lúc trước). Tôi không biết tại sao điều này đôi khi hoạt động và đôi khi thất bại. Nó thật kì lạ. Tôi đã kết thúc bằng cách sử dụng một cách giải quyết trong đó tôi có được thời gian hiện tại và đặt nó làm biến số, sau đó tạm dừng tập lệnh cho đến khi thời gian thay đổi cộng thêm một phút (rõ ràng là trễ 1 phút). Điều đó thật rắc rối, nhưng nó đã hoạt động hoàn hảo trong nhiều tháng, trong khi một sự chậm trễ đơn giản đã bị gián đoạn. Ừ
2oh1

Tôi đang chạy 10.10.5 và giải pháp này không hoạt động và cũng khóa tập lệnh trong suốt thời gian ngủ
Greg

@Greg: Nếu nó khóa script script thời gian ngủ thì nó hoạt động. /bin/sleepchờ thời gian ngủ và không trở lại cho đến khi nó hoàn thành. Ngược lại, delaylệnh tích hợp của AppleScript xử lý các sự kiện đầu vào của người dùng trong khi tập lệnh bị tạm dừng. (Đó là lỗi nằm ở đâu: nếu có đầu vào bàn phím của người dùng, hãy delaytiếp tục thực thi tập lệnh trước khi thời gian trì hoãn hoàn thành.)
Chris Trang

3

Tôi không nói đây là giải pháp tốt nhất, nhưng dường như nó đã giải quyết được vấn đề của tôi. Thay vì sử dụng một độ trễ đơn giản, bị bỏ qua vì những lý do tôi không hiểu, tôi đã chuyển sang lấy thời gian và lặp cho đến khi đạt được thời gian mới (nó vẫn sử dụng độ trễ, nhưng nó không thành vấn đề nếu nó bỏ qua độ trễ do tập lệnh không tiếp tục cho đến khi đạt được thời gian).

# Pause for five minutes
set GetTheTime to current date
set NewTime to GetTheTime + (5 * minutes)
repeat while (current date) is less than NewTime
    delay 60
end repeat

Tôi vẫn đang muốn biết tại sao sự chậm trễ lại bị phớt lờ (hoặc tăng tốc đột ngột ?! ??), nhưng điều này đã hoàn thành công việc, vụng về như nó vốn có.


Lệnh "trì hoãn" không được "tăng tốc", nó bị gián đoạn. Trong khi trì hoãn, nó nằm trong một vòng lặp kiểm tra xem có bất kỳ sự kiện đầu vào bàn phím nào để nó có thể kiểm tra Thời gian lệnh. Rõ ràng là nó không chính xác thoát khỏi vòng lặp trì hoãn khi phát hiện bất kỳ đầu vào của người dùng.
Chris Trang

Hấp dẫn! Tôi thấy rằng nó bị bỏ qua (tăng tốc? Bị gián đoạn?) Ngay cả khi máy Mac của tôi đang ngồi không, nhưng tôi không biết tại sao.
2oh1

Khi một sự kiện đầu vào của người dùng nằm trong hàng đợi sự kiện, delaysẽ tiếp tục bị gián đoạn cho đến khi một cái gì đó xử lý các sự kiện và xóa chúng khỏi hàng đợi.
Chris Trang

2

Tôi tìm thấy một công việc xung quanh trong một bài viết diễn đàn Đức . Thêm các dòng này vào đầu tập lệnh của bạn:

use framework "Foundation"
use scripting additions
current application's NSThread's sleepForTimeInterval:1

Tôi đang gặp sự cố khi kiểm tra câu trả lời của bạn bởi vì, vì bất kỳ lý do gì, độ trễ hiện đang hoạt động như mong đợi trên máy Mac của tôi. Tôi không biết tại sao. Tôi đang chạy 10.10.3. Có lẽ Apple đã sửa lỗi này? Hoặc, có thể đó chỉ là một sự cố không liên tục không ảnh hưởng đến máy Mac của tôi tại thời điểm này. Ừ Như tôi đã nói ở trên, cách giải quyết của tôi là Applescript có được thời gian hiện tại và sau đó trì hoãn cho đến thời điểm hiện tại cộng với x.
2oh1

Tôi cũng đang chạy 10.10.3 và vẫn thấy vấn đề. Vì không phải ai cũng nhìn thấy vấn đề, nên có lẽ nó không liên tục hoặc liên quan đến phần mềm của bên thứ 3 hoặc các cài đặt ưu tiên nhất định. Ai biết. BTW, công việc của bạn có lẽ có nhược điểm là ứng dụng tiếp tục sử dụng 100% thời gian CPU trong khi chờ đợi, trong khi hành vi trì hoãn thích hợp là đặt ứng dụng ngủ trong thời gian đó, do đó sử dụng ít năng lượng hơn.
Thomas Tempelmann

Tôi đang chạy 10.10.5 và giải pháp này không hoạt động.
Greg

@ThomasTempelmann: Sự cố xảy ra khi có đầu vào của người dùng. Nếu bạn không nhấp hoặc gõ trong khi tập lệnh đang chạy, lỗi không được kích hoạt.
Chris Trang

Lưu ý rằng giải pháp này khiến ứng dụng thực sự đóng băng trong suốt thời gian ngủ. delayxử lý đầu vào của người dùng trong khi đoạn script bị tạm dừng, vì vậy bạn vẫn có thể tương tác với các menu và cửa sổ chẳng hạn.
Chris Trang

0

carzyj đã có những gì tôi cho là câu trả lời hay nhất, nhưng khi kết hợp với phương pháp của Chris Page, bạn sẽ nhận được:

on delay duration
  do shell script "/bin/sleep " & duration
end delay

Bạn có thể nhận xét "về độ trễ" thông qua "độ trễ kết thúc" để trở lại độ trễ ban đầu.


Tôi cũng đã thực hiện một sửa đổi mã tương tự, trước khi thấy điều này. Tôi đang chạy 10.10.5 và giải pháp này không hoạt động và cũng khóa tập lệnh trong suốt thời gian ngủ.
Greg

0

đây là một sửa đổi cho giải pháp @ chris-page

Nó dường như là một sự cân bằng giữa khả năng đáp ứng và nắm bắt chính xác độ trễ.

on delay duration
    set endTime to (current date) + duration
    repeat while (current date) is less than endTime
        set delta to duration / 100
        if duration < 0.2 then
            set delta to 0.2
        end if
        tell AppleScript to delay delta
    end repeat
end delay

Nhưng thay vì bảo Applescript trì hoãn trong thời gian tổng thể, chúng tôi chỉ bảo nó trì hoãn trong một khoảng thời gian nhỏ. nếu khoảng thời gian nhỏ hơn mức táo cho phép (1/60 giây), thì hãy đặt nó vào đồng bằng đó. Rằng chúng ta có thể giữ một số phản hồi, nhưng vẫn chính xác. sự nghi ngờ là đôi khi độ trễ không hoạt động nên vòng lặp while sẽ giữ luồng bị khóa, nhưng trong các kịch bản thành công, chúng tôi muốn độ trễ delta bị ngắn để quá trình vẫn có thể bị gián đoạn


Việc rút ngắn độ trễ yêu cầu là không cần thiết và chỉ có thể làm cho tập lệnh chạy chậm hơn và tiêu tốn nhiều CPU hơn trong khi chờ đợi. Phiên bản của tôi chỉ đơn thuần gọi độ trễ cho đến khi hết thời lượng mong muốn, cho phép delaytrì hoãn hết mức có thể trước khi tiếp tục thực thi.
Chris Trang

Lưu ý rằng vì câu trả lời này đã được đăng, tôi đã cập nhật mã của mình để sử dụng delay endTime - (current date)thay vì delay duration, điều này đảm bảo rằng nếu delay không bị gián đoạn, nó sẽ không tạm dừng tập lệnh lâu hơn thời gian yêu cầu ban đầu, có thể là những gì bạn đang cố gắng địa chỉ với câu trả lời này.
Chris Trang

0

Vì vậy, để kết hợp tất cả lại, tôi tin rằng Chris có nghĩa là:

on delay duration
   set endTime to (current date) + duration
   repeat while (current date) is less than endTime
      tell AppleScript to delay endTime - (current date)
   end repeat
end delay
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.