2008-09-18 16 views
6

Trong ứng dụng web asp.net, tôi muốn ghi vào một tệp. Trước tiên, hàm này sẽ lấy dữ liệu từ cơ sở dữ liệu và sau đó ghi ra tệp phẳng.Bạn muốn ghi vào một tệp, nhưng có thể có nhiều nhà văn tiềm năng cùng một lúc, cần phải khóa

Tôi có thể làm gì để đảm bảo chỉ có 1 lần ghi xảy ra, và khi quá trình ghi xảy ra, các chủ đề khác có thể muốn ghi vào tệp không phải do quá trình ghi diễn ra.

Tôi muốn thực hiện công việc này CHỈ nếu nó chưa được thực hiện trong 15 phút.

Tôi biết có một từ khóa khóa, vì vậy tôi nên bọc tất cả mọi thứ trong một khóa, sau đó kiểm tra xem nó đã được cập nhật trong 15 phút hoặc nhiều hơn, hoặc ngược lại?

Cập nhật

Workflow:

Vì đây là một ứng dụng web, nhiều trường hợp sẽ là người xem một trang web cụ thể. Tôi có thể sử dụng xây dựng trong hệ thống bộ nhớ cache, nhưng nếu asp.net tái chế nó sẽ là tốn kém để xây dựng lại bộ nhớ cache vì vậy tôi chỉ muốn viết nó ra một tập tin phẳng. Lựa chọn khác của tôi sẽ chỉ là tạo một dịch vụ windows, nhưng đó là nhiều công việc để quản lý mà tôi muốn.

+0

Tất cả các bài viết có xảy ra trong một trường hợp đơn lẻ của một ứng dụng không? Hoặc sẽ có nhiều trường hợp của ứng dụng đang cố gắng viết cùng một lúc hoặc các ứng dụng khác nhau sẽ cố gắng viết cùng một lúc? –

Trả lời

2

Đồng bộ hóa mã viết của bạn để khóa trên một đối tượng được chia sẻ sao cho chỉ có một luồng nằm trong khối. Những người khác đợi cho đến khi thoát hiện tại.

lock(this) 
{ 
    // perform the write. 
} 

Cập nhật: Tôi giả định rằng bạn có một đối tượng được chia sẻ. Nếu đây là những quá trình khác nhau trên cùng một máy, bạn cần một thứ như một Mutex có tên. Looky here for an example

+0

Tôi nghĩ rằng điều này sẽ không hoạt động, vì những lý do tôi đã giải thích dưới đây. – MarkR

1

không nên khóa một biến đối tượng chứ không phải toàn bộ trường hợp?

0

Tôi không tin rằng khóa của .NET được áp dụng cho các quy trình khác nhau. Hơn nữa, khóa (điều này) sẽ chỉ loại trừ các chủ đề khác đang chạy phương thức trên cùng một ví dụ "này" - vì vậy các chủ đề khác ngay cả trong cùng một quá trình có thể chạy cùng một lúc trên các trường hợp khác nhau.

Giả sử tất cả các quy trình của bạn đang chạy trên cùng một máy, việc khóa tệp phải thực hiện.

Nếu bạn đang sử dụng các máy khác nhau, số dặm của bạn có thể khác nhau- win32 yêu cầu có khóa tệp hoạt động trên mạng, nhưng các ứng dụng lịch sử dựa vào đó (Think MSAccess) có vấn đề với tham nhũng tệp.

+0

Bạn có quyền để khóa hoạt động, bạn sẽ cần tất cả các phương pháp để sử dụng cùng một ví dụ của "this". Giải pháp ở đây có thể là tạo một đối tượng giả ** tĩnh ** để đảm bảo điều đó. –

0
// try enter will return false if another thread owns the lock 
    if (Monitor.TryEnter(lockObj)) 
    { 
     try 
     { 
     // check last write time here, return if too soon; otherwise, write 
     } 
     finally 
     { 
     Monitor.Exit(lockobj); 
     } 
    } 
+0

cũng chính xác như khóa (lockObj) {}. –

1

Các thao tác I/O ghi vào tệp sẽ tự động khóa tệp. Kiểm tra xem tập tin có bị khóa không (bằng cách thử viết) và nếu nó không ghi. Trước khi thực hiện bất kỳ ghi nào, hãy kiểm tra dấu thời gian trên tệp và xem thời gian của tệp đó có dài hơn 15 phút hay không.

afaik bạn không thể ghi vào tệp mà không bị khóa bởi Windows/bất kỳ điều gì.

Bây giờ tất cả những gì còn lại dành cho bạn là tra cứu cách thực hiện trên bằng cách sử dụng msdn (xin lỗi, tôi không thể bận tâm tìm kiếm tất cả và tôi không nhớ các lớp C# rất tốt). :)

+1

Lưu ý, câu trả lời của tôi phụ thuộc vào dấu thời gian là đáng tin cậy - không phải luôn luôn là một giả định tốt. Thay vào đó, bạn có thể để tệp mở, không được viết trong 15 phút, sau khi quá trình hoàn tất ghi. :) – jheriko

0

Sử dụng ổ khóa tập tin hệ thống

Giống như những người khác đề nghị,.NET sẽ bị hạn chế sử dụng trong tình huống này. Đây là mã:

FileInfo fi = new FileInfo(path); 
if (fi.Exists 
    && (DateTime.UtcNow - fi.LastWriteTimeUtc < TimeSpan.FromMinutes(15)) { 
    // file is fresh 
    return; 
} 

FileStream fs; 
try { 
    fs = new FileStream(
    path, FileMode.Create, FileAccess.Write, FileShare.Read); 
} catch (IOException) { 
    // file is locked 
    return; 
} 

using (fs) { 
    // write to file 
} 

này sẽ làm việc trên đề quy trình.

0

Các bạn nên xem xét Mutex. Nó có thể đồng bộ hóa giữa nhiều luồng và quy trình.

Các vấn đề liên quan